Dual POC — Consumer Theming

Two override surfaces a consumer uses to re-theme without forking CSS: semantic variables — the system-wide, meaning-named colors like "action fill" that cascade to every component — and component variables, named for one specific component and scoped to it alone. The pickers below write the real --dual-* custom properties live onto each stage — no rebuild.

Base theme mode (click to recolor the page):

Semantic override — one change, everything re-themes

Set a semantic variable on a scope (here the stage element) and every component under it inherits it. This is the primary consumer theming path — a brand recolor is a handful of semantic vars, not per-component edits. ("Content" = the text/foreground color that sits on the fill.)

Scope: this stage carries the semantic overrides

Card title

Both button and card inherit the semantic vars above — neither declares its own fill here.

Component override — scoped to one component

When a consumer needs one component off-brand (a warning button, a highlighted card) without touching the rest, they set the component variable. It overrides only that component; siblings still follow the semantic layer.

Scope: only the component vars are set — semantic layer untouched

Card (component fill)

Changing --dual-button-fill here does not touch the card, and vice-versa — component vars are per-component.

Precedence — component var falls back to semantic

Each component variable is authored as var(--dual-button-fill, var(--dual-action-fill-1)): use the component override if set, otherwise the semantic value. So a consumer overrides at whichever layer fits — broad brand change at the semantic layer, targeted exception at the component layer.

/* component/button/button.variables.scss (authored) */
/* the 2nd arg of var() is the fallback: use --dual-button-fill if set, else --dual-action-fill-1 */
--dual-button-fill: var(--dual-action-fill-1);          /* defaults to the semantic layer */
--dual-button-content: var(--dual-action-content-1);

/* consumer: broad brand recolor — every component follows */
:root { --dual-action-fill-1: #6d28d9; }

/* consumer: one-off exception — only the button, semantic layer intact */
.checkout .Dual-Button { --dual-button-fill: #b91c1c; }
Consumer intentOverride atWhat it affects
Rebrand the whole productsemantic (--dual-action-*, --dual-base-*, …) on :rootevery component
Theme a section/subtreesemantic vars on a wrapper, or [data-dual-theme]that subtree
One component off-brandcomponent var (--dual-button-fill, …)that component only

See Token Architecture for how these vars are generated, and SCSS Structure for where component vars are authored.