Tokens
The full reference, generated from packages/tokens/src. Version 0.2.1.
Three tiers: primitive (color.neutral.600), semantic (color.action.primary), component (button.height.md). Components reference semantic tokens only. Three modes apply on any element: data-theme, data-density and data-motion. The foundations explain when to use each token.
Colour ramps
The primitive tier. Status ramps share identical lightness steps; the neutral ramp is cool grey.
neutral
- 0
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 850
- 900
- 950
- 1000
accent
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
success
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
warning
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
critical
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
info
- 50
- 100
- 200
- 300
- 400
- 500
- 600
- 700
- 800
- 900
- 950
Semantic colours
The tier components use. Surfaces are a layer ladder: canvas, layer-1, layer-2, layer-3, each with a hover token. Contrast is computed from the oklch values against the background each token is paired with.
surface
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| surface.canvas | oklch(0.985 0.002 250) | oklch(0.11 0.01 250) | — |
| surface.layer-1 | oklch(1 0 0) | oklch(0.15 0.012 250) | — |
| surface.layer-1-hover | oklch(0.965 0.003 250) | oklch(0.21 0.012 250) | — |
| surface.layer-2 | oklch(0.985 0.002 250) | oklch(0.21 0.012 250) | — |
| surface.layer-2-hover | oklch(0.965 0.003 250) | oklch(0.25 0.012 250) | — |
| surface.layer-3 | oklch(0.965 0.003 250) | oklch(0.25 0.012 250) | — |
| surface.layer-3-hover | oklch(0.925 0.005 250) | oklch(0.29 0.012 250) | — |
| surface.overlay | oklch(1 0 0) | oklch(0.21 0.012 250) | — |
| surface.inverse | oklch(0.15 0.012 250) | oklch(0.985 0.002 250) | — |
fg
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| fg.primary | oklch(0.15 0.012 250) | oklch(0.985 0.002 250) | 19.67:1 AAA18.84:1 AAA on surface.layer-1 |
| fg.secondary | oklch(0.38 0.012 250) | oklch(0.87 0.007 250) | 10.00:1 AAA13.28:1 AAA on surface.layer-1 |
| fg.muted | oklch(0.48 0.012 250) | oklch(0.66 0.01 250) | 6.53:1 AA6.33:1 AA on surface.layer-1 |
| fg.placeholder | oklch(0.53 0.012 250) | oklch(0.66 0.01 250) | 5.27:1 AA6.33:1 AA on surface.layer-1 |
| fg.disabled | oklch(0.66 0.01 250) | oklch(0.48 0.012 250) | 3.11:1 AA-large3.01:1 AA-large on surface.layer-1 |
| fg.inverse | oklch(1 0 0) | oklch(0.15 0.012 250) | 19.67:1 AAA18.84:1 AAA on surface.inverse |
| fg.numeric | oklch(0.11 0.01 250) | oklch(1 0 0) | 20.45:1 AAA19.67:1 AAA on surface.layer-1 |
| fg.link | oklch(0.45 0.18 262) | oklch(0.79 0.12 262) | 7.74:1 AAA10.11:1 AAA on surface.layer-1 |
| fg.link-hover | oklch(0.38 0.15 262) | oklch(0.88 0.08 262) | 10.32:1 AAA13.68:1 AAA on surface.layer-1 |
| fg.on-accent | oklch(1 0 0) | oklch(1 0 0) | 6.00:1 AA6.00:1 AA on action.primary |
line
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| line.subtle | oklch(0.965 0.003 250) | oklch(0.21 0.012 250) | — |
| line.default | oklch(0.925 0.005 250) | oklch(0.29 0.012 250) | — |
| line.strong | oklch(0.53 0.012 250) | oklch(0.53 0.012 250) | 5.27:1 AA3.73:1 AA-large on surface.layer-1 |
| line.inverse | oklch(0.38 0.012 250) | oklch(0.87 0.007 250) | — |
action
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| action.primary | oklch(0.51 0.2 262) | oklch(0.51 0.2 262) | — |
| action.primary-hover | oklch(0.45 0.18 262) | oklch(0.45 0.18 262) | — |
| action.primary-active | oklch(0.38 0.15 262) | oklch(0.38 0.15 262) | — |
| action.primary-fg | oklch(1 0 0) | oklch(1 0 0) | 6.00:1 AA6.00:1 AA on action.primary |
| action.secondary | oklch(1 0 0) | oklch(0.15 0.012 250) | — |
| action.secondary-hover | oklch(0.985 0.002 250) | oklch(0.21 0.012 250) | — |
| action.secondary-active | oklch(0.965 0.003 250) | oklch(0.29 0.012 250) | — |
| action.secondary-fg | oklch(0.15 0.012 250) | oklch(0.985 0.002 250) | 19.67:1 AAA18.84:1 AAA on action.secondary |
| action.secondary-line | oklch(0.66 0.01 250) | oklch(0.48 0.012 250) | — |
| action.ghost-hover | oklch(0.965 0.003 250) | oklch(0.21 0.012 250) | — |
| action.ghost-active | oklch(0.925 0.005 250) | oklch(0.29 0.012 250) | — |
| action.destructive | oklch(0.53 0.2 27) | oklch(0.53 0.2 27) | — |
| action.destructive-hover | oklch(0.46 0.17 27) | oklch(0.46 0.17 27) | — |
| action.destructive-active | oklch(0.39 0.14 27) | oklch(0.39 0.14 27) | — |
| action.destructive-fg | oklch(1 0 0) | oklch(1 0 0) | 5.85:1 AA5.85:1 AA on action.destructive |
| action.disabled | oklch(0.925 0.005 250) | oklch(0.29 0.012 250) | — |
| action.disabled-fg | oklch(0.53 0.012 250) | oklch(0.66 0.01 250) | 4.23:1 AA-large4.54:1 AA on action.disabled |
status
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| status.neutral | oklch(0.48 0.012 250) | oklch(0.66 0.01 250) | 6.53:1 AA6.33:1 AA on surface.layer-1 |
| status.neutral-bg | oklch(0.965 0.003 250) | oklch(0.21 0.012 250) | — |
| status.neutral-fg | oklch(0.29 0.012 250) | oklch(0.925 0.005 250) | 12.74:1 AAA14.20:1 AAA on status.neutral-bg |
| status.neutral-line | oklch(0.66 0.01 250) | oklch(0.48 0.012 250) | — |
| status.neutral-solid | oklch(0.38 0.012 250) | oklch(0.87 0.007 250) | — |
| status.neutral-solid-fg | oklch(1 0 0) | oklch(0.11 0.01 250) | 10.00:1 AAA13.81:1 AAA on status.neutral-solid |
| status.success | oklch(0.5 0.14 152) | oklch(0.68 0.15 152) | 5.62:1 AA7.27:1 AAA on surface.layer-1 |
| status.success-bg | oklch(0.97 0.03 152) | oklch(0.24 0.05 152) | — |
| status.success-fg | oklch(0.37 0.1 152) | oklch(0.88 0.1 152) | 9.23:1 AAA11.70:1 AAA on status.success-bg |
| status.success-line | oklch(0.6 0.15 152) | oklch(0.5 0.14 152) | — |
| status.success-solid | oklch(0.44 0.12 152) | oklch(0.68 0.15 152) | — |
| status.success-solid-fg | oklch(1 0 0) | oklch(0.11 0.01 250) | 7.34:1 AAA7.56:1 AAA on status.success-solid |
| status.warning | oklch(0.6 0.15 60) | oklch(0.75 0.16 70) | 4.13:1 AA-large8.58:1 AAA on surface.layer-1 |
| status.warning-bg | oklch(0.98 0.03 80) | oklch(0.25 0.05 50) | — |
| status.warning-fg | oklch(0.41 0.11 50) | oklch(0.9 0.12 80) | 8.69:1 AAA11.91:1 AAA on status.warning-bg |
| status.warning-line | oklch(0.6 0.15 60) | oklch(0.6 0.15 60) | — |
| status.warning-solid | oklch(0.83 0.15 75) | oklch(0.83 0.15 75) | — |
| status.warning-solid-fg | oklch(0.11 0.01 250) | oklch(0.11 0.01 250) | 11.88:1 AAA11.88:1 AAA on status.warning-solid |
| status.critical | oklch(0.53 0.2 27) | oklch(0.68 0.18 27) | 5.85:1 AA6.30:1 AA on surface.layer-1 |
| status.critical-bg | oklch(0.97 0.02 27) | oklch(0.25 0.07 27) | — |
| status.critical-fg | oklch(0.39 0.14 27) | oklch(0.88 0.08 27) | 9.38:1 AAA11.09:1 AAA on status.critical-bg |
| status.critical-line | oklch(0.6 0.21 27) | oklch(0.53 0.2 27) | — |
| status.critical-solid | oklch(0.53 0.2 27) | oklch(0.53 0.2 27) | — |
| status.critical-solid-fg | oklch(1 0 0) | oklch(1 0 0) | 5.85:1 AA5.85:1 AA on status.critical-solid |
| status.info | oklch(0.52 0.13 230) | oklch(0.68 0.12 230) | 5.35:1 AA7.01:1 AAA on surface.layer-1 |
| status.info-bg | oklch(0.97 0.02 230) | oklch(0.24 0.05 230) | — |
| status.info-fg | oklch(0.38 0.09 230) | oklch(0.88 0.07 230) | 9.04:1 AAA11.54:1 AAA on status.info-bg |
| status.info-line | oklch(0.6 0.13 230) | oklch(0.52 0.13 230) | — |
| status.info-solid | oklch(0.52 0.13 230) | oklch(0.68 0.12 230) | — |
| status.info-solid-fg | oklch(1 0 0) | oklch(0.11 0.01 250) | 5.35:1 AA7.29:1 AAA on status.info-solid |
| status.accent | oklch(0.51 0.2 262) | oklch(0.68 0.16 262) | 6.00:1 AA6.72:1 AA on surface.layer-1 |
| status.accent-bg | oklch(0.97 0.02 262) | oklch(0.24 0.08 262) | — |
| status.accent-fg | oklch(0.38 0.15 262) | oklch(0.88 0.08 262) | 9.47:1 AAA11.54:1 AAA on status.accent-bg |
| status.accent-line | oklch(0.58 0.19 262) | oklch(0.51 0.2 262) | — |
| status.accent-solid | oklch(0.51 0.2 262) | oklch(0.51 0.2 262) | — |
| status.accent-solid-fg | oklch(1 0 0) | oklch(1 0 0) | 6.00:1 AA6.00:1 AA on status.accent-solid |
field
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| field.bg | oklch(1 0 0) | oklch(0.11 0.01 250) | — |
| field.bg-hover | oklch(0.985 0.002 250) | oklch(0.15 0.012 250) | — |
| field.bg-disabled | oklch(0.965 0.003 250) | oklch(0.21 0.012 250) | — |
| field.line | oklch(0.66 0.01 250) | oklch(0.48 0.012 250) | 3.11:1 AA-large3.13:1 AA-large on field.bg |
| field.line-hover | oklch(0.53 0.012 250) | oklch(0.53 0.012 250) | — |
| field.line-invalid | oklch(0.53 0.2 27) | oklch(0.6 0.21 27) | — |
| field.line-disabled | oklch(0.87 0.007 250) | oklch(0.29 0.012 250) | — |
focus
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| focus.ring | oklch(0.51 0.2 262) | oklch(0.68 0.16 262) | 6.00:1 AA6.72:1 AA on surface.layer-1 |
data
| Token | Light | Dark | Contrast (light / dark) |
|---|---|---|---|
| data.1 | oklch(0.51 0.2 262) | oklch(0.68 0.16 262) | — |
| data.2 | oklch(0.6 0.13 230) | oklch(0.68 0.12 230) | — |
| data.3 | oklch(0.6 0.15 152) | oklch(0.68 0.15 152) | — |
| data.4 | oklch(0.6 0.15 60) | oklch(0.75 0.16 70) | — |
| data.5 | oklch(0.6 0.21 27) | oklch(0.68 0.18 27) | — |
| data.6 | oklch(0.53 0.012 250) | oklch(0.66 0.01 250) | — |
| data.positive | oklch(0.44 0.12 152) | oklch(0.68 0.15 152) | — |
| data.negative | oklch(0.46 0.17 27) | oklch(0.68 0.18 27) | — |
Typography
Fifteen named roles. Every string on screen uses one through <Text>; numeric roles set tabular numerals and the 7:1 numeric colour. Type does not change with density.
| Variant | Sample | Size / leading | Weight / tracking |
|---|---|---|---|
| display-lg | The quick brown fox settles the invoice | 1.875rem / 2.25rem | 600 / -0.02em |
| display-md | The quick brown fox settles the invoice | 1.5rem / 2rem | 600 / -0.02em |
| heading-lg | The quick brown fox settles the invoice | 1.25rem / 1.75rem | 600 / -0.01em |
| heading-md | The quick brown fox settles the invoice | 1rem / 1.5rem | 600 / -0.01em |
| heading-sm | The quick brown fox settles the invoice | 0.875rem / 1.25rem | 600 / 0em |
| body-lg | The quick brown fox settles the invoice | 1rem / 1.5rem | 400 / 0em |
| body-md | The quick brown fox settles the invoice | 0.875rem / 1.25rem | 400 / 0em |
| body-sm | The quick brown fox settles the invoice | 0.8125rem / 1.125rem | 400 / 0em |
| label-md | The quick brown fox settles the invoice | 0.875rem / 1.25rem | 500 / 0em |
| label-sm | The quick brown fox settles the invoice | 0.75rem / 1rem | 500 / 0em |
| caption | The quick brown fox settles the invoice | 0.6875rem / 1rem | 400 / 0.04em |
| numeric-lg | $12,480.00 | 1.5rem / 2rem | 600 / -0.01em |
| numeric-md | $12,480.00 | 0.875rem / 1.25rem | 500 / 0em |
| numeric-sm | $12,480.00 | 0.75rem / 1rem | 500 / 0em |
| code | txn_1Nv2hZ · acct_4421 | 0.8125rem / 1.25rem | 400 / 0em |
Space
A 4 px scale. Tailwind's spacing utilities (p-4, gap-2) map to it.
| Token | Value | Utility | Scale |
|---|---|---|---|
| space.0 | 0px | p-0 | |
| space.1 | 4px | p-1 | |
| space.2 | 8px | p-2 | |
| space.3 | 12px | p-3 | |
| space.4 | 16px | p-4 | |
| space.5 | 20px | p-5 | |
| space.6 | 24px | p-6 | |
| space.7 | 28px | p-7 | |
| space.8 | 32px | p-8 | |
| space.9 | 36px | p-9 | |
| space.10 | 40px | p-10 | |
| space.12 | 48px | p-12 | |
| space.16 | 64px | p-16 | |
| space.20 | 80px | p-20 | |
| space.24 | 96px | p-24 | |
| space.px | 1px | p-px | |
| space.0-5 | 2px | p-0.5 | |
| space.1-5 | 6px | p-1.5 | |
| space.2-5 | 10px | p-2.5 |
Layout and size
Semantic distances and control sizes. The compact column is the value under data-density="compact"; everything else stays the same.
| Token | Comfortable | Compact | Utility |
|---|---|---|---|
| size.target.min WCAG 2.2 SC 2.5.8 minimum target size | 24px | same | min-h-target-min |
| size.control.sm | 28px | 24px | h-control-sm |
| size.control.md | 32px | 28px | h-control-md |
| size.control.lg | 40px | 32px | h-control-lg |
| size.topbar Height of the application TopBar. Sticky elements below it offset by this. | 56px | 48px | h-topbar · top-topbar |
| size.sidenav Width of the SideNav. | 240px | same | w-sidenav |
| layout.gutter Gap between grid columns. | 24px | 16px | gap-gutter |
| layout.margin Page padding at the edge of the main area. | 32px | 24px | px-margin |
| layout.section Space between page sections. | 32px | 24px | py-section · gap-section |
| layout.stack-xs | 4px | same | gap-stack-xs |
| layout.stack-sm | 8px | same | gap-stack-sm |
| layout.stack-md | 16px | 12px | gap-stack-md |
| layout.stack-lg | 24px | 16px | gap-stack-lg |
| layout.inline-sm | 8px | same | gap-inline-sm |
| layout.inline-md | 12px | same | gap-inline-md |
| layout.card-x | 20px | 12px | px-card-x (Card padding md) |
| layout.card-y | 16px | 12px | py-card-y (Card padding md) |
| layout.card-x-sm | 16px | 8px | px-card-x-sm (Card padding sm) |
| layout.card-y-sm | 12px | 8px | py-card-y-sm (Card padding sm) |
| layout.grid.columns Columns in the page grid. Divides into 2, 3, 4 and 6. | 12 | same | layout-grid |
| layout.container.prose | 720px | same | max-w-prose |
| layout.container.form | 640px | same | max-w-form |
| layout.container.page | 1280px | same | max-w-page |
| layout.container.wide | 1536px | same | max-w-wide |
Radius
Radii of 8 px or less (DECISIONS.md #15). Semantic shapes name what each radius is for.
Elevation
Tone first, border second, shadow last. Four named roles.
Z-index
Named layers; never a raw z-index.
| Token | Value | Utility | Use for |
|---|---|---|---|
| z.base | 0 | z-base | Page content. |
| z.raised | 10 | z-raised | An element lifted inside its section, such as a dragged row. |
| z.sticky | 100 | z-sticky | TopBar, the PageHeader tab row, sticky table headers. |
| z.dropdown | 1000 | z-dropdown | Select lists and menus. |
| z.overlay | 1100 | z-overlay | The scrim behind a dialog. |
| z.modal | 1200 | z-modal | Dialogs and sheets. |
| z.popover | 1300 | z-popover | Popovers opened from inside a dialog. |
| z.toast | 1400 | z-toast | Toasts and the focused skip link. |
| z.tooltip | 1500 | z-tooltip | Tooltips, above everything. |
Motion
Durations, easings and the one named animation. Reduced motion is honoured at the token layer, so components never branch on it.
Each bar moves with its own duration and the standard easing. Reduced motion collapses all of them to 0 ms.
- duration.instant
- duration.fast
- duration.base
- duration.slow
| Token | Value | Reduced motion | Utility |
|---|---|---|---|
| duration.instant | 0ms | 0ms | duration-instant |
| duration.fast | 100ms | 0ms | duration-fast |
| duration.base | 160ms | 0ms | duration-base |
| duration.slow | 240ms | 0ms | duration-slow |
| duration.spin | 1000ms | 0ms | duration-spin |
| ease.standard | cubic-bezier(0.2, 0, 0, 1) | unchanged | ease-standard |
| ease.enter | cubic-bezier(0, 0, 0.2, 1) | unchanged | ease-enter |
| ease.exit | cubic-bezier(0.4, 0, 1, 1) | unchanged | ease-exit |
| animation.spin | macaw-spin 1000ms linear infinite | none | animate-spin |