Getting started

Tokens

How color, light, radius and motion are organised.

Tokens come in two layers. The palette holds raw values and nothing else; the semantic layer names roles and points them at palette steps. A component only ever references a role, so retheming means editing the semantic layer and nothing under components/.

/* layer 1: the only place a hex lives */
--neutral-900: #171717;

/* layer 2: roles */
--brand: var(--neutral-900);
--ring: color-mix(in oklab, var(--brand) 45%, var(--background));

Palette

One achromatic ramp, --neutral-50 to --neutral-950, plus four status ramps: green, amber, blue and red. There is no decorative hue. Color in Blank means a status, a data delta or your brand, nothing else.

Two accents

primary is the action color: the filled button. brand is the identity color: focus rings, selection, checked marks, active indicators, progress. Both start as the same ink, so the system reads black and white until you turn brand. Theming shows how.

Colors

Surfaces

--background
--card
--popover
--muted
--accent
--sidebar
--inverted

Action

--primary
--secondary
--brand
--brand-subtle
--destructive

Lines & fields

--border
--input
--input-field
--input-hover
--input-disabled
--ring

Interactive items

--item-outline
--item-outline-hover
--item-secondary
--item-secondary-hover
--item-selected
--item-destructive-subtle

Status

--success
--success-primary
--warning
--warning-primary
--info
--info-primary
--danger
--danger-primary

Charts use --chart-1 to --chart-5, steps of the ink from strongest to faintest. A series that means up, down or failed uses the success and danger roles instead.

Light

Raised surfaces are lit, not outlined. Two tokens carry the light:

TokenLightDarkUsed by
--highlightwhitewhite at 7%the top edge of a card: shadow-[inset_0_1px_0_var(--highlight)]
--glowink at 6%white at 14%the soft light that falls into a bento card

Radius

Everything derives from --radius (10px by default), so the system rounds together. Controls are pills (rounded-full) at any radius.

TokenValueUsed by
--radius-lgvar(--radius)small surfaces
--radius-xlcalc(var(--radius) + 2px)textarea, menu and select items
--radius-2xlcalc(var(--radius) + 6px)card, popover, menu, toast, alert
--radius-3xlcalc(var(--radius) + 10px)bento card
--radius-4xlcalc(var(--radius) + 14px)dialog, drawer, sheet
--radius-full9999pxbuttons, inputs, tabs, badges

Motion

Three easings live in the theme, so they are Tailwind utilities (ease-out, ease-in-out, ease-spring). Every transition-* utility uses ease-out unless told otherwise.

TokenCurveUsed for
--ease-outcubic-bezier(0.23, 1, 0.32, 1)anything that enters or reacts
--ease-in-outcubic-bezier(0.77, 0, 0.175, 1)anything that moves on screen
--ease-springcubic-bezier(0.34, 1.56, 0.64, 1)a press, a pop, the switch thumb

Feedback takes 100–150ms, menus open in 150ms and close in 100ms, panels slide in 250–300ms.

Inverted surfaces

A dark menu on a light page is a surface, not a color family. Set data-inverted on a popover-like element and it re-points --popover, --muted-foreground, --border and the item states at their inverted counterparts — every part inside keeps working unchanged.

<SelectContent inverted>…</SelectContent>