Skip to content

Foundations

Design tokens

Two layers. tokens.css holds raw values — palette, type ramp, space, radius, motion. theme.css maps them to semantic names, and components only ever read those. Light and dark are the same semantic names with different values, resolved from a single data-theme attribute on <html>.

Two names in that map do the accessibility heavy lifting: the interactive colour is --an-accent (ink, not a hue), and control boundaries use --an-border-control rather than the decorative hairline. Both are measured on the accessibility page.

Colour

Surfaces

Canvas --an-bg
Surface --an-surface
Raised --an-surface-raised
Sunken --an-surface-sunken
Hover --an-surface-hover
Inverse --an-surface-inverse

Content & lines

Text --an-text
Muted --an-text-muted
Faint --an-text-faint
Hairline --an-border
Hairline strong --an-border-strong
Control border --an-border-control

Interactive, brand & status

Accent (ink) --an-accent
Emphasis --an-accent-emphasis
Accent soft --an-accent-soft
Brand --an-brand
Brand strong --an-brand-strong
Success --an-success
Warning --an-warning
Danger --an-danger
Info --an-info

Typography

The ramp, the two families and every canonical pairing live on their own page — Typography — because type is where most of the day-to-day decisions get made, and a swatch grid is the wrong place to answer them.

Space, radius, elevation

Space

1
2
3
4
5
6
8
10
12
16

Radius

xs
sm
md
lg
xl
2xl

Elevation

Surfaces are flat by default: a card shares the page's colour and is found by its hairline, in both themes. Only two things break the plane — something recessed goes down a step (sunken, the nav rail), and something genuinely floating over the page casts a shadow. Nothing rises by getting lighter, except in dark, where a shadow over near-black is invisible and raised has to lift with tone instead.

xs
sm
md
lg
xl

Motion

Material 3's duration and easing scales, mirrored in tokens.css and motion/tokens.ts — so a CSS transition and a Svelte transition run the identical curve. Press replay and watch the difference between the standard and emphasized families.

Easing

--an-ease-standard Colour, opacity, small state changes
--an-ease-emphasized The default for anything that moves
--an-ease-emphasized-decelerate Entering: menus, dialogs, sheets
--an-ease-emphasized-accelerate Leaving: dismissals
--an-ease-spring Toggles and thumbs — the only overshoot

Duration

--an-duration-short-2 100ms
--an-duration-short-4 200ms
--an-duration-medium-2 300ms
--an-duration-medium-4 400ms
--an-duration-long-2 500ms

Theming an app

css
/* Rebrand by redefining the semantic layer — never by
   overriding component selectors. */
:root {
  --an-accent: #0a84ff;
  --an-accent-soft: #dceafd;
  --an-radius-md: 6px;      /* squarer controls  */
  --an-press-scale: 1;      /* opt out of the press squish */
}