Naming Conventions
Token Tiers
Section titled “Token Tiers”Tokens are organized into three tiers. Each tier has a distinct purpose, its own naming convention, and a clear dependency direction: higher tiers reference lower tiers, never the reverse. Every tier starts with the token category (color, spacing, radius, opacity, typography, shadow, duration, zindex, ...).
| Tier | Purpose | Convention | Example |
|---|---|---|---|
| Base | Raw values without intent | Descriptive, type-grouped | color.palette.blue-500 |
| Semantic | Intent-based, themeable | Six-layer path | color.action.brand.hover |
| Component | UI-mapped, per-component | Five-layer path | color.button.primary.background.hover |
The reference chain flows in one direction:
Component tokens → Semantic tokens → Base tokensBase Token Naming
Section titled “Base Token Naming”Base tokens are the raw building blocks. They represent values without intent and use neutral, descriptive names grouped under a type-specific namespace:
| Category | Base group | Example tokens |
|---|---|---|
| Color | color.palette | color.palette.blue-500, color.palette.gray-900, color.palette.white |
| Spacing | spacing.scale | spacing.scale.xs, spacing.scale.sm, spacing.scale.md |
| Radius | radius.scale | radius.scale.none, radius.scale.sm, radius.scale.md, radius.scale.full |
| Opacity | opacity.scale | opacity.scale.0, opacity.scale.50, opacity.scale.100 |
| Shadow | shadow.raw | shadow.raw.sm, shadow.raw.md, shadow.raw.lg |
| Typography | font.* | font.family.sans, font.size.lg, font.weight.bold |
| Duration | duration.scale | duration.scale.fast, duration.scale.normal, duration.scale.slow |
| Z-Index | zindex.scale | zindex.scale.dropdown, zindex.scale.modal, zindex.scale.toast |
(And more — common categories include breakpoints, easing, motion, sizing depending on your system.)
Base tokens sit outside the six-layer semantic convention. Semantic tokens reference them via {color.palette.blue-500} style aliases.
Semantic Tokens: The Six-Layer Path
Section titled “Semantic Tokens: The Six-Layer Path”Every semantic token path is a subsequence of six ordered layers:
category.concept.sentiment.prominence.state.scale| Layer | Purpose | Example values |
|---|---|---|
| category | Token type or domain | color, spacing, typography, shadow |
| concept | What it’s used for | text, background, surface, action, border, icon, overlay, gap, inset, heading, body, elevation |
| sentiment | Semantic intent or role | neutral, brand, danger, success, warning, info |
| prominence | Visual weight or emphasis | muted, subtle, strong, inverse |
| state | Interaction state | hover, active, focus, disabled, selected |
| scale | Size or intensity step | xs, sm, md, lg, xl, 2xl |
Each layer has its own distinct vocabulary — values never overlap between layers. muted is always prominence. danger is always sentiment. hover is always state. md is always scale. This means layers can be omitted when they’re not needed, and there’s never ambiguity about which layer a segment belongs to.
Ordering Rule
Section titled “Ordering Rule”Layers can be skipped, but they can never be reordered. Every token path must be a subsequence of the full six-layer order — broadest classification first, most specific last.
color.text.danger.muted is valid (sentiment then prominence). color.text.muted.danger is not (prominence before sentiment — going backwards).
Most tokens use two to four layers:
| Token path | Layers used |
|---|---|
color.text | category + concept |
color.text.muted | category + concept + prominence |
color.text.danger | category + concept + sentiment |
color.text.muted.disabled | category + concept + prominence + state |
color.background.danger.subtle | category + concept + sentiment + prominence |
color.action.brand.hover | category + concept + sentiment + state |
spacing.gap.md | category + concept + scale |
typography.heading.lg | category + concept + scale |
How Categories Use Layers
Section titled “How Categories Use Layers”Different token categories lean on different subsets:
- Color tokens typically use concept through state and skip scale.
- Spacing, typography, and shadow tokens typically use concept and scale, skipping sentiment, prominence, and state.
The convention is the same — each category uses the subset it needs.
Comprehensive Examples
Section titled “Comprehensive Examples”| Token path | Category | Concept | Sentiment | Prominence | State | Scale |
|---|---|---|---|---|---|---|
color.text | color | text | — | — | — | — |
color.text.muted | color | text | — | muted | — | — |
color.text.danger | color | text | danger | — | — | — |
color.text.danger.muted | color | text | danger | muted | — | — |
color.text.muted.disabled | color | text | — | muted | disabled | — |
color.background | color | background | — | — | — | — |
color.background.danger.subtle | color | background | danger | subtle | — | — |
color.surface | color | surface | — | — | — | — |
color.action.brand | color | action | brand | — | — | — |
color.action.brand.hover | color | action | brand | — | hover | — |
color.action.danger.strong.active | color | action | danger | strong | active | — |
color.border | color | border | — | — | — | — |
color.border.focus | color | border | — | — | focus | — |
color.icon.success | color | icon | success | — | — | — |
spacing.gap.md | spacing | gap | — | — | — | md |
spacing.inset.lg | spacing | inset | — | — | — | lg |
typography.heading.lg | typography | heading | — | — | — | lg |
typography.body.sm | typography | body | — | — | — | sm |
shadow.elevation.md | shadow | elevation | — | — | — | md |
Principles
Section titled “Principles”- Intent over implementation.
color.action.brandinstead ofcolor.blue-500. When your brand color changes from blue to purple, you rename zero tokens. - Predictability. If
color.textexists, a developer can guess thatcolor.text.mutedandcolor.text.subtleprobably do too. - Orthogonal layers. Sentiment, prominence, state, and scale answer different questions: “what role?”, “how loud?”, “what interaction?”, and “what size?” Keeping them separate prevents naming collisions and makes the system composable.
- No going back. Layers always appear in the canonical order. You can skip, but you can’t reorder. This keeps every path unambiguous.
Mapping to DTCG JSON
Section titled “Mapping to DTCG JSON”Each layer becomes a nesting level in the JSON structure:
{ "color": { "text": { "$type": "color", "$root": { "$value": "{color.palette.gray-900}" }, "muted": { "$root": { "$value": "{color.palette.gray-500}" }, "disabled": { "$value": "{color.palette.gray-300}" } }, "danger": { "$value": "{color.palette.red-500}" } }, "action": { "$type": "color", "brand": { "$root": { "$value": "{color.palette.blue-500}" }, "hover": { "$value": "{color.palette.blue-600}" } } } }, "spacing": { "gap": { "$type": "dimension", "sm": { "$value": "{spacing.scale.sm}" }, "md": { "$value": "{spacing.scale.md}" }, "lg": { "$value": "{spacing.scale.lg}" } } }}When a node needs to be both a token and a group (e.g. color.text.muted has a value and a child disabled), use $root to hold the node’s own value while allowing children alongside it.
Dispersa flattens this structure during parsing, so color.text.muted and color.action.brand.hover are the token paths you see in build output.
Component Token Naming
Section titled “Component Token Naming”Component tokens sit above the semantic layer. They map semantic tokens to specific UI components, creating a stable contract between design and implementation. Like the other tiers, they start with the token category. Each component token path is a subsequence of six ordered layers:
category.component.variant.slot.property.state| Layer | Purpose | Example values |
|---|---|---|
| category | Token type or domain | color, spacing, typography, shadow |
| component | UI component name | button, card, input, badge, tooltip |
| variant | Optional variant or role | primary, secondary, ghost, success, danger |
| slot | Optional component part | icon, avatar, badge, label, indicator (or any custom slot name) |
| property | CSS-ish concern | background, text, border, padding, shadow, radius, gap |
| state | Optional interaction state | hover, active, focus, disabled, selected |
The same ordering rule applies: layers can be skipped but never reordered. Variant, slot, and state are optional; category, component, and property are required.
Semantic concepts (text, background, action, border…) and component names (button, card, input, badge…) are naturally distinct vocabularies, so there is no ambiguity when both live under the same category namespace like color.*.
Component Token Examples
Section titled “Component Token Examples”| Token path | Category | Component | Variant | Slot | Property | State |
|---|---|---|---|---|---|---|
color.button.primary.background | color | button | primary | — | background | — |
color.button.primary.background.hover | color | button | primary | — | background | hover |
color.button.primary.icon.background | color | button | primary | icon | background | — |
color.button.secondary.border | color | button | secondary | — | border | — |
color.button.danger.background | color | button | danger | — | background | — |
color.card.background | color | card | — | — | background | — |
spacing.card.avatar.padding | spacing | card | — | avatar | padding | — |
color.input.border | color | input | — | — | border | — |
color.input.border.focus | color | input | — | — | border | focus |
color.input.danger.border | color | input | danger | — | border | — |
color.badge.success.background | color | badge | success | — | background | — |
Mapping to DTCG JSON
Section titled “Mapping to DTCG JSON”Component tokens follow the same nesting pattern, with category as the outermost level. A single component’s tokens may span multiple categories:
{ "color": { "button": { "primary": { "background": { "$type": "color", "$root": { "$value": "{color.action.brand}" }, "hover": { "$value": "{color.action.brand.hover}" }, "active": { "$value": "{color.action.brand.active}" } }, "text": { "$type": "color", "$value": "{color.text.inverse}" } } }, "input": { "border": { "$type": "color", "$root": { "$value": "{color.border}" }, "focus": { "$value": "{color.border.focus}" } } } }, "spacing": { "button": { "primary": { "padding": { "$type": "dimension", "$value": "{spacing.gap.md}" } } } }}Reference Chain
Section titled “Reference Chain”Component tokens should reference semantic tokens, not base tokens directly. This keeps the dependency chain clean and ensures theming works end-to-end:
color.button.primary.background → {color.action.brand} (semantic)color.action.brand → {color.palette.blue-500} (base)Skipping the semantic layer (e.g., color.button.primary.background → {color.palette.blue-500}) creates a shortcut that bypasses theming — when the theme changes, that component token won’t update.