@flipdish/ui-tokens
Design tokens for the Flipdish Design System — brand colours, type scale, spacing, and shadows — shipped as a single Tailwind CSS v4 @theme stylesheet that both web (Tailwind) and React Native (NativeWind v5) consume.
Internal design system, published publicly. These tokens encode Flipdish's brand. They're on the public npm registry so they can be shared across Flipdish micro-frontends and apps, not as a general-purpose token set.
Part of the Flipdish Design System:
| Package | Purpose |
|---|---|
@flipdish/ui-tokens | Design tokens (this package) |
@flipdish/ui-icons | Icon set |
@flipdish/ui-library | Components |
@flipdish/ui-connected | API-connected components |
Installation
pnpm add @flipdish/ui-tokens
No runtime dependencies and no peer dependencies — the package ships one CSS file.
Usage
Web and React Native import the same file. The @theme block populates Tailwind's design system with the token vocabulary, so semantic utilities like bg-primary, text-secondary, and border-primary resolve via CSS custom properties.
Web (Tailwind v4)
@import the CSS from your Tailwind entry stylesheet:
@import "@flipdish/ui-tokens/css" layer(theme); /* tokens + [data-theme="dark"] */
React Native (NativeWind v5)
Add the same import to the global.css NativeWind compiles. NativeWind v5's react-native-css reads Tailwind v4 @theme blocks directly, so no JS theme object or tailwind.config.js preset is needed. See the React Native installation guide for the full global.css shape and the lightningcss pin it requires.
/* global.css, alongside the other imports from the installation guide */
@import "@flipdish/ui-tokens/css" layer(theme);
The Flipdish brand ramp is authored in hex so both Tailwind and react-native-css parse it identically.
Semantic tokens
Tokens are layered: theme-invariant primitives (raw colour ramps, scales) and a semantic mapping (--color-bg-*, --color-fg-*, --color-text-*, --color-border-*, --color-focus-ring) that follows the Untitled UI v8 vocabulary, so Untitled UI components render on-brand out of the box.
Always consume the semantic layer — it's what stays theme-aware:
// ✓ Correct — semantic token, theme-aware
<div className="bg-primary text-secondary border-primary" />
// ✗ Wrong — primitive token, breaks theme switching
<div className="bg-neutral-50 text-neutral-900" />
// ✗ Wrong — raw CSS variable reference
<div style={{ background: "var(--color-bg-primary)" }} />
The same suffix means different things per property: bg-primary is the page background, while text-primary is the near-black body text.
Theme switching
Light is the default. On web, dark mode activates declaratively via a [data-theme="dark"] attribute on the mount node (or any ancestor) — no JavaScript runtime theme-switching code required:
<!-- Light (default) -->
<div id="app">…</div>
<!-- Dark -->
<div id="app" data-theme="dark">…</div>
On React Native there is no DOM attribute to cascade from, so the [data-theme="dark"] block does not apply and semantic tokens keep their light values in both device schemes. NativeWind's dark: variants still follow the device colour scheme.
Changelog
See CHANGELOG.md for release history.
Contributing
This package lives in the flipdish-design-system monorepo. Contributor documentation — how to change a token, the primitive/semantic structure, and what the build-time lint checks — lives alongside the source there.