Theming

Two token layers: neutral surfaces that build a depth ladder, and eight colour sets any component can be pointed at with one prop.

Colour sets

A colour set assigns six --ui-* variables. Every colourable variant reads them, so one prop restyles solid, secondary, outline and ghost together.

One prop, four variants
tsx
<Button color="blue">Solid</Button>
<Button color="blue" variant="secondary">Secondary</Button>
<Button color="blue" variant="outline">Outline</Button>
<Button color="blue" variant="ghost">Ghost</Button>

// Or any CSS colour at all — fill, text, hover and border are derived:
<Button tint="#7c3aed">Custom</Button>
neutralbluevioletcyangreenamberrosedestructive

Hover is a token, not a calculation

Hover values are declared per theme rather than derived by mixing. A mix has to pick a direction, and the right direction flips: a light fill darkens, a dark one lightens. One formula is wrong in one theme.

The surface ladder

With no shadows, depth is carried by lightness alone. Each step sits above the last:

SurfaceDarkUsed by
page0.08--background
card body0.13--card, --popover
card header0.15muted at 40% over the card
group0.18--secondary, the tray behind cards
hover0.20--accent
Lowering opacity does not lighten
On a dark theme an opacity modifier blends toward the page, which pulls lightness down. Reaching for /50 to lighten a surface is how the group once ended up darker than the card header it sits above.