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>.
| Path | Reads as |
|---|---|
color.bg.action.brand.default | Background color, action role, brand context, default state. |
color.bg.action.brand.hover | …same, hover state. |
color.text.on.brand | Text color when placed on top of a brand fill. |
color.border.focus | Border color used for focus rings. |
space.4 | The 4-step on the spacing scale (16px). |
radius.md | Medium 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 CSScore.json semantic.*.json button.cssA 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 typedcssVar(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.