Skip to content

Tokens overview

helixui tokens are authored in W3C DTCG JSON. The source files live in packages/tokens/tokens/:

  • core.json — primitive values (color ramps, spacing scale, radii, type, shadows). Not for direct use in components.
  • semantic.light.json — intent-based aliases. Components consume these. References primitives via {color.brand.500} syntax.
  • semantic.dark.json — same shape as light, different primitive references.

Naming

Token paths read as a sentence: <category>.<role>.<context>.<state>.

PathReads as
color.bg.action.brand.defaultBackground color, action role, brand context, default state.
color.bg.action.brand.hover…same, hover state.
color.text.on.brandText color when placed on top of a brand fill.
color.border.focusBorder color used for focus rings.
space.4The 4-step on the spacing scale (16px).
radius.mdMedium corner radius (8px).

In CSS the same paths become --helixui- prefixed kebab-case variables: color.bg.action.brand.default → --helixui-color-bg-action-brand-default.

Layers

primitive → semantic → component CSS
core.json semantic.*.json button.css

A component never reaches into core.json. It composes semantic tokens. This means:

  • Theming is alias swapping. Dark mode rebinds the same semantic names to different primitives.
  • Renaming a primitive does not break components. Only the semantic mapping changes.

Build outputs

Run pnpm build:tokens. Outputs:

  • dist/css/core.css — primitive CSS variables on :root.
  • dist/css/semantic.css — semantic CSS variables, themed via [data-theme="light"|"dark"].
  • dist/css/all.css — both, in order.
  • dist/index.{js,d.ts} — TypeScript types and a typed cssVar(path) helper.
  • dist/manifest.json — flat AI-readable manifest. One entry per token with value, type, description, layer, and per-theme resolutions.

Why not Style Dictionary?

Style Dictionary is great. We chose a 200-line script instead because the build chain is part of the public API of an AI-friendly system: an LLM that wants to reason about how a token becomes a CSS variable can read the script in one minute. We may swap to Style Dictionary later if scope demands it; the JSON source is portable either way.