The three token tiers

Primitive, semantic and component tokens — why only one tier holds raw values, and the naming grammar that makes the system machine-checkable.

FDS organizes tokens into three tiers. The rule that makes re-theming cheap: raw values (hex colors, px sizes) exist ONLY in the primitive tier — everything above is an alias.

TierCSS prefixExample idRole
Primitive (ref)--fx-ref-*ref.brand.600Raw scales — the only tier with literals
Semantic--fx-*color.primary, space.4Intent-named aliases — what you should use
Component--fx-c-*c.button.radiusNarrow aliases for one component's knobs

Why aliases all the way up

A theme (or a brand change) never edits a component: it re-points aliases. Dark mode re-points color.bg from ref.neutral.0 to ref.neutral.900; a brand swap re-points color.primary to a new primitive. Every component that reads var(--fx-color-primary) updates for free.

Components read semantic tokens, never primitives. If a button hardcoded ref.brand.600 it would survive a theme swap unchanged — which is exactly the bug this architecture prevents.

Naming grammar

Every token has a dot-path id whose segments are lowercase kebab-case, and a deterministic CSS variable: color.on-primary--fx-color-on-primary. The mapping is pure (tokenIdToCssVar), so tooling never needs a lookup table.

import { tokenIdToCssVar, hasToken, tokenType, getToken } from 'flexa-design-system';

tokenIdToCssVar('space.4');   // '--fx-space-4'
hasToken('color.primary');    // true — the vocabulary gate
tokenType('shadow.md');       // 'shadow' (DTCG $type)
getToken('color.primary');    // full registry entry (tier, refs, value)

The `on-X` convention

Every filled color X ships a paired on-X for the text/icon that sits on it: color.primary / color.on-primary, color.danger / color.on-danger. These pairs are contrast-checked in CI (WCAG 2.2 AA) in both light and dark — see the contrast matrix on the Tokens page.

Reserved namespaces

The first segment of every token id (color, space, radius, ref, c, …) is a reserved namespace. isTokenNamespace(segment) is the discriminator validation tools use: a dot-path inside a reserved namespace that is NOT a known token is an off-system token (a typo or an unregistered custom id) and gets rejected, while img.png or 1.5px are ordinary CSS literals and pass through untouched.