Foundations / Color system
Color system
The palette every Alpha component paints from, in a dark mode and a light one. Only the neutral ramp holds raw greys — text, surfaces, borders and controls are declared as references into it, so retinting the ramp moves everything built on top of it.
One primitive ramp, everything else on top
Only the neutral ramp holds raw greys. Every neutral-derived token — text, surfaces, borders, the secondary button — is declared as a reference into it, exactly as the source palette declares it. The ramp inverts between modes, so one unchanged declaration paints two colours:
:root,
[data-mode='dark'] {
--neutral-900: #f9f9f9;
--text-typical: var(--neutral-900);
}
[data-mode='light'] {
--neutral-900: #333333;
--text-typical: var(--neutral-900);
}The chips below are filled with the token itself rather than a copy of its value, so toggling the theme in the header repaints them. Printed values have their references resolved per mode, dark first — a swatch reading #f9f9f9 / #333333 is one declaration, not two. Colours the source stores as literals stay literals here even where two of them happen to match today, so a future divergence cannot hide behind an alias.
The primitives
The index counts distance from the surface, not lightness: 900 is the furthest from the page and therefore the text colour in both modes. Base --neutral is the nearest surface — white in light, near-black in dark. Retint these and everything aliased to them moves.
--text-inverse is the label on a solid fill and is near-white in both modes, which is why it is the only one here that does not simply follow the ramp.
Depth 0 is the nearest surface — a card — and the deepest is the page behind it. The order is the same in both modes even though the greys invert.
Each family carries a hover and a pressed value; Button is the only group with full interaction states, and it is not the only component that reads them. Button reaches for --button-primary, --button-secondary, --button-neutral-surface and --button-inactive, which is the fill of a disabled button rather than an opacity applied over one. Dropdown takes --button-secondary-hover for an engaged trigger and a highlighted row, and the same --button-inactive when it is turned off. The success, warning and danger families are here because the palette defines them; nothing in Alpha renders them yet.
The brand indigo and the status hues, for anything that is not a button — a focus ring, a badge, an inline message.
Tooltip reads these two at a time: background and text for the regular fill, the inverted pair for variant="inverted", and a background on its own for additional, which keeps the regular text. The regular pair flips with the mode — a dark chip on a light page and a light one on a dark page — so the inverted pair is the one that matches the page rather than opposing it. --tooltip-text-translucent is the exception: it is reserved for a metric tooltip, and nothing renders it.
Categorical series in order, each with a hover. The source names them after a hue; the name here is the ordinal, because that is what a chart indexes by — and because the hue is not reliable: several of them are a different colour from the Vivid hue they share a name with, which is why the two groups are declared independently.
Base, hover and pressed for each hue, for surfaces that need to be told apart rather than ranked.
Pale washes for tinted backgrounds — the ghost destructive button hovers onto --aquarelle-red. They are opaque and tuned against Depth 0, so on any other surface they read as a patch rather than a tint.
Brand constants, and the only colours identical in both modes.
Retinting is the supported way to theme Alpha — override a token, never a component class. Override it in the same two-block shape the package uses: a bare :root rule comes later in the cascade at equal specificity, so it would land on both modes at once.
:root,
[data-mode='dark'] {
--primary: #0f766e;
}
[data-mode='light'] {
--primary: #0d6157;
}Because the semantics alias into the ramp, retinting --neutral-900 alone moves --text-typical, --text-inverse, --tooltip-text and --tooltip-background-inverted with it.
These names are not namespaced — --primary and --chart-1 are ordinary global custom properties, so they match the hand-off exactly and collide with an application that already defines them. If yours does, rename it or scope Alpha to a subtree.