Tokens
Every color, space, and radius a component draws comes from a named token — never a literal value. Tokens are a two-layer system: primitive ramps hold the raw brand values, and semantic aliases give those values a job. Components only ever name the alias, which is what lets the whole library re-theme, and switch between light and dark, without a single component changing.
From primitives to semantics
A primitive is a value in the brand ramp. A semantic alias points at one and carries the intent — this is background, this is body text. The alias is the only thing a component names, so the same code resolves to the right value in each theme.
// A primitive: a raw value in the brand ramp (never referenced by a component)
colors.nearBlack = '#0f1728'
// A semantic alias: what components actually consume
tokens.color.text.primary = colors.nearBlack // light theme
darkTokens.color.text.primary = colors.dashboardDarkText // dark theme
// In a component, you only ever name the alias:
<Text color="textPrimary">Readable in both themes</Text>
The four families
Semantic color splits into four families by where the color lands: bg* fills a surface, text* colors rendered words, fg* tints icons and graphics, and border* draws edges. Reach for the family that matches the mark you are painting.
bg* — surfaces
bgPrimary
Page and card ground
bgSecondary
Muted panels and rows
bgTertiary
Recessed wells
bgBrandSolid
The one brand-filled surface
bgInverse
Dark-on-light overlays
text* — rendered words
textPrimary
Body and headings
textSecondary
Supporting copy
textTertiary
Captions and hints
textBrandPrimary
Links and brand emphasis
fg* — icons and graphics
fgPrimary
Default icon and glyph tint
fgSecondary
Quieter icons
fgSuccess
Positive status marks
fgError
Destructive status marks
border* — edges
borderPrimary
Default hairline
borderStrong
High-contrast dividers
borderBrand
Focused and selected edges
fg* versus text*
These two look interchangeable and are not. text* is for letterforms — anything the reader parses as words. fg* is for foreground graphics — icon strokes, illustration marks, the check inside a checkbox. When a label and its icon sit together, they usually take the matching pair.
Order confirmed
<CheckIcon color="fgSuccess" />
<Text color="textSuccess">Order confirmed</Text>
The check is a graphic, so it takes fg*. The words are text, so they take text*. The Icon primitive even defaults its color to fgPrimary for exactly this reason — an icon that borrowed a text* token would be a small lie about what it is.
Status roles travel in trios
Success, warning, error, and info each ship as a matched set — a bg*, an fg*, and a border* that are tuned to sit together. Use them as a set (bgSuccess behind fgSuccess inside borderSuccess) rather than mixing a status fill with an unrelated foreground.
bgSuccess / textSuccess / borderSuccess
bgWarning / textWarning / borderWarning
bgError / textError / borderError
bgInfo / textInfo / borderInfo
Light and dark share the names
There is one alias vocabulary and two value sets behind it — tokens for light, darkTokens for dark. bgPrimary is a near-white in one and a near-black in the other, but the component only ever writes bgPrimary. That is the whole reason a literal color is a bug: it cannot follow the theme, so it will be wrong in one of them.
This page is written entirely in aliases. Switch your system between light and dark and every swatch above re-resolves on its own — nothing here special-cases a theme.
Edit them live
The token editor lets you retint any token in this vocabulary and watch every component respond in place — the fastest way to feel how a single alias fans out across the library, and to sanity-check a rebrand before it touches the ramp.
The library is held to this
Token discipline is not a convention you have to remember — it is enforced. The catalog audit (tools/audit-catalog.mjs, rule "Token discipline (NFR-T1/T2)") scans the library source for hard-coded colors in style positions (backgroundColor, borderColor, shadowColor, and the rest) and for raw shadow values, and the catalog gate fails on any finding.
// Flagged by the audit — a hard-coded color in a style position:
<Box style={{ backgroundColor: '#ffffff' }} />
// Correct — a semantic alias that resolves per theme:
<Box backgroundColor="bgPrimary" />
The rule was not written in the abstract: it came from two real bugs — DatePicker and CommandMenu both hard-coded a modal scrim while a scheme-aware overlay token already existed — and it now keeps that class of mistake from reaching the catalog at all.