Foundations
Six rules the whole library obeys. They explain why the tokens are shaped the way they are, and they are the reason a new component almost never needs a new value.
- rules
- 6
- elevations
- 4
- inks
- 3
- accent
- 1
Step 1: Surfaces stack, they do not tint
Five planes, from the page behind the window to the tiles nested inside a card. Depth comes from the stack order and a hairline, not from shadow.
app — content area inside the window
surface — a card
tile — bordered, nested
field — filled input
sunken — read-only row
Only four elevations exist. Everything else separates with a line hairline, which is why cards can sit 16px apart without the page feeling noisy.
Step 2: Three inks, always in the same order
Primary carries the value, secondary the label, tertiary the meta. A row never uses two inks of the same rank.
$27,829.83
ink
Values, headings, row titles
Inactive item
ink-soft
Secondary text, inactive nav
Monthly Plan
ink-faint
Captions, meta, placeholders
Step 3: One accent, spent sparingly
The accent marks exactly one thing per region: the current page, the primary action, the earned part of a meter. Status colours exist but the design barely uses them.
Primary action
Current page
Qualifier
Unread
Selected
Step 4: Radius grows with the container
A 12px glyph sits inside a 14px tile, inside a 20px card, inside a 32px window. Nesting a larger radius inside a smaller one never happens.
12
window32pxApp frame
card20pxCards
tile14pxNested tiles, menus
glyph12pxIcon plates, rate rows
Step 5: Interaction is a colour change
Hover shifts one step along the same ramp — accent to accent-strong, line to line-strong, transparent to surface-muted. Nothing moves, scales or lifts.
accent → accent-strong
Rest
Hover
line → line-strong
Live
Hover or tab to these
Step 6: Focus is global and visible
A single base rule gives every focusable element a 2px accent-strong outline offset by 2px. Components never remove it and never reimplement it.
Tab through these
Focus rings are not shown on click, only on keyboard focus
Icon-only controls take a required label, which becomes both the accessible name and the tooltip. There is no way to render one without a name.