Themes & multiple brands
Build light/dark and multi-brand themes with tokens, CSS variables and live reconfiguration.
1 min readv1
There are three ways to theme, from most static to most dynamic.
1. Tokens + dark:#
Fine for a single brand with a dark mode. Pairs live side by side in recipes:
TypeScript
components: {
surface: "bgc=$color.surface; cl=$color.ink; dark:bgc=$color.surface-dark; dark:cl=#e2e8f0",
}2. Tokens pointing at CSS variables#
One set of markup, any number of themes — switch by changing variables:
TypeScript
tokens: {
color: {
brand: "var(--brand)",
surface: "var(--surface)",
ink: "var(--ink)",
},
},CSS
:root { --brand: #4F52D9; --surface: #fff; --ink: #0f172a; }
.dark { --brand: #8A8DF0; --surface: #0b0f19; --ink: #e2e8f0; }
[data-brand=acme] { --brand: #e11d48; }HTML
<div nib="--brand=#e11d48; d=flex; g=8px">
<button nib="p=8px 14px; bdrd=8px; bd=none; cl=#fff; bgc=var(--brand)">Acme brand</button>
<button nib="--brand=#16a34a; p=8px 14px; bdrd=8px; bd=none; cl=#fff; bgc=var(--brand)">Green brand</button>
</div>No dark: rules are needed any more — the variables change instead.
3. Live reconfiguration#
The runtime can swap the whole config and re-style every element — for theme editors and white-label previews:
TypeScript
runtime.configure({
...config,
tokens: { ...config.tokens, color: { ...config.tokens.color, brand: picker.value } },
});