Tokens

Design tokens in Roadie v2 are CSS custom properties defined via Tailwind v4's @theme directive. They provide a single source of truth for colors, typography, spacing, and theming — automatically supporting dark mode via the .dark class.

How tokens work

Tokens are defined in packages/core/src/css/tokens.css and consumed via Tailwind utility classes or CSS custom properties:

/* Import in your app's CSS */
@import '@oztix/roadie-core/css';
{/* Use via intent + emphasis utilities */}
<div className="intent-accent emphasis-subtle text-normal p-4 rounded-xl">
Content using the intent/emphasis system
</div>

Token layers

1. Color scales (primitive)

Raw OKLCH color values in 14 steps (0-13) per scale. Available scales:

  • neutral — grays for UI structure
  • brand — Oztix Blue (fixed)
  • brand-secondary — Oztix Orange (fixed)
  • accent — customizable per collection (defaults to brand)
  • danger — red for errors and destructive actions
  • success — green for positive outcomes
  • warning — yellow for caution states
  • info — purple for informational states

Usage: bg-neutral-3, text-accent-11, border-danger-7

2. Intent system (semantic)

Intent utilities set --intent-* CSS custom properties that provide the color context. Children inherit the intent via CSS cascade:

{/* Set intent on a container — children inherit */}
<div className="intent-accent">
<button className="emphasis-strong is-interactive rounded-full px-4 py-2">
Accent button
</button>
</div>
{/* Or set intent directly on the element */}
<button className="intent-danger emphasis-strong is-interactive rounded-full px-4 py-2">
Danger button
</button>

Each intent exposes:

  • Surface: --intent-surface-default (step 1), subtle (3), subtler (2), strong (9), inverted (12), raised (0), sunken (2)
  • Border: --intent-border-subtler (5), subtle (6), default (7), strong (9)
  • Foreground: --intent-fg-subtler (10), subtle (11), default (12), strong (13), inverted (0)
  • Raw steps: --intent-0 through --intent-13 for granular access

3. Emphasis system (visual)

Emphasis utilities consume intent tokens to apply visual styles:

{/* Combined shortcuts */}
<div className="intent-accent emphasis-strong">Solid accent bg + white text</div>
<div className="intent-accent emphasis-subtle">Tinted accent bg + dark text</div>
{/* Property-specific (composable) */}
<div className="intent-accent bg-strong text-subtle">
Solid accent bg + colored text
</div>

4. Typography

Fluid font sizes with clamp() from lg upward, plus pre-composed text style utilities:

{/* Tailwind size utilities */}
<p className="text-lg">Fluid large text</p>
{/* Text style composites */}
<h1 className="text-display-ui-1">App heading</h1>
<h1 className="text-display-prose-1">Article heading</h1>
<p className="text-prose">Body paragraph</p>

Dark mode

All tokens automatically adapt via the .dark class on <html>. The OKLCH color values swap — step numbers stay the same but perceptual weight inverts. No dark: Tailwind variants needed for colors.

{/* Semantic classes adapt to dark mode automatically */}
<div className="bg-normal text-normal border border-subtle p-4 rounded-xl">
Adapts to light/dark automatically
</div>
{/* Intent + emphasis on a button */}
<button className="intent-accent emphasis-strong is-interactive rounded-full px-4 py-2">
Always uses the right colors
</button>

Dynamic accent color

The accent scale can be overridden at runtime for per-collection branding:

import { ThemeProvider } from '@oztix/roadie-components'
<ThemeProvider defaultAccentColor="#FF6B00">
{/* All intent-accent elements use orange */}
</ThemeProvider>

For SSR, use getAccentStyleTag() to inject colors server-side and avoid flash.

Best practices

  1. Use intent + emphasis for component colors — not raw scale steps
  2. Use Tailwind utilities for spacing and layout (p-4, gap-2, grid)
  3. Let dark mode happen automatically — the token system handles it
  4. Use the accent intent for primary actions — it adapts to dynamic theming
  5. Use neutral intent for structural UI — it's the default, no class needed on :root

For a complete reference of all available tokens, see the Token reference page.