Token architecture
Three layers — rendered
Higher layers resolve down, never up. Components consume semantic. Semantic resolves to primitive. Component-local stays inside the component file.
What lives in each global sheet
The global sheet retains: color, type, spacing, semantic surfaces, motion, status, action accent, glass, sheet, modal, input, focus.
Component-local tokens (e.g., --topbar-h, --reqlog-bg, --actlib-card-w) live in their component's CSS module, not in the global sheet.
Why three layers
- Theming. Dark mode rebinds layer 2; primitives never move.
- Naming honesty.
--peach-2is descriptive;--accent-defaultsays what it does. Two registers, two layers. - Co-location. Component-local lives next to the component — the global sheet doesn't grow forever.
When to add a token
- Re-use first. If an existing semantic name covers your case, use it.
- New value → add the primitive in
@matter/tokens. Then add a semantic alias if the use is product-wide. - One-screen private → keep it in the component's CSS module.
See Authoring rules for the PR workflow.
--surface-elevated from a screen author. Primitives are for the brand layer.Hover
Tone cascade — every hover defaults to the closest non-neutral color in its ancestor chain. White, black, and grey are the explicit opt-out, never the default.
Accessibility — AA contract
Body text 4.5:1 minimum, UI and large text 3:1. Decorative tokens are exempt — sibling AA aliases exist for callsites that need to flip.