Theming it¶
Everything visual comes from 27 knobs. Override them on :root — after the stylesheet — and the
rest of the system follows.
A rebrand¶
That is the whole rebrand. Hover, active, tint, wash, border, focus ring and the readable text
shade of the brand are all color-mix() derivations of that one colour, so they move with it
and stay in proportion.
A denser or roomier product¶
Every padding, gap and margin follows — and so does every control height, because heights are derived from the line box plus a step of the space scale rather than written as literals. A density knob that reaches a button's padding but not its height is not a density knob.
Shape and depth¶
:root {
--ads-radius-scale: 0; /* square everything */
--ads-radius-scale: 2; /* twice as round */
--ads-shadow-strength: 0; /* flat design */
--ads-shadow-strength: 2; /* heavy */
--ads-shadow-color: light-dark(rgb(40 20 10), rgb(0 0 0)); /* a warm shadow */
}
Shadow geometry is fixed; the strength knob multiplies the opacity of every layer. Colour is separate so a warm shadow stays possible.
Neutrals¶
Neutrals are a hue and a chroma multiplier, not thirty hex codes:
:root {
--ads-neutral-hue: 260; /* violet-leaning chrome */
--ads-neutral-chroma: 0; /* pure grey */
--ads-neutral-chroma: 2; /* twice the colour */
}
The per-step saturation is not flat — a good ramp gets more saturated as it darkens — so the knob scales that curve rather than replacing it.
Two themes on one page¶
The tokens are declared on :root and [data-ads-scope], so any subtree can carry its own:
<body>
<!-- the product -->
<div data-ads-scope style="--ads-brand: #7c3aed; --ads-radius-scale: 2">
<!-- a white-labelled panel, with its own brand and shape -->
</div>
</body>
Useful for an embedded partner panel, a preview pane in a theme editor, or a multi-tenant dashboard.
Accessible intents¶
The reference's palette is the default because matching it is the default. It is also below WCAG AA when an intent colour is used as text: measured on its own tint, Tabler's success reads 2.48:1, warning 2.73:1, info 2.77:1, where the floor for body text is 4.5.
--ads-contrast: 1 pushes each intent's ink far enough to clear it — success 4.97, warning
5.39, info 5.44 — and leaves every fill, border and tint exactly where it was. So the design does
not change; only the text does. It is a scalar rather than a switch, so a project can sit
anywhere between the two.
What not to override¶
Derived tokens are fair game, but overriding one breaks the link that makes the system coherent:
/* Don't. --ads-space-4 is derived; now it no longer follows the scale. */
:root { --ads-space-4: 19px; }
If you find yourself reaching for a derived token, the honest options are to move the knob, or to add a token upstream. Both are cheaper than the fork.
The full list¶
Every knob, its default and what it reaches: Reference → Knobs.