Skip to content

Token architecture

Three layers — rendered

Layer 3

Component-local

Co-located with the component CSS file that owns it.

--topbar-h--actlib-card-w--folder-icon-w
Layer 2

Semantic

Intent names. The layer callsite authors reach for.

--surface-page--text-primary--line-default
Layer 1

Primitive

Raw values — hex, alpha, gradient stops. Source of truth.

--peach-2--ink-8--paper-55

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-2 is descriptive; --accent-default says 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

  1. Re-use first. If an existing semantic name covers your case, use it.
  2. New value → add the primitive in @matter/tokens. Then add a semantic alias if the use is product-wide.
  3. One-screen private → keep it in the component's CSS module.

See Authoring rules for the PR workflow.

Reach for --surface-elevated from a screen author. Primitives are for the brand layer.
Don't add a brand-new color primitive to solve a one-off design ask — it bloats the back room forever.

On this page