Theming

How a brand palette becomes CSS variables every component reads.

BrandTheme writes each token of the palette to a CSS variable on its own element. Components read only these variables, so you can nest themes, show two brands side by side, or switch at runtime.

Tokens

TokenCSS variableUsed for
surface--bs-surfacePage background
elevated--bs-elevatedCards, fields, popups
ink--bs-inkText
muted--bs-mutedSecondary text, field borders
accent--bs-accentPrimary actions, focus rings, highlights
onAccent--bs-on-accentText on the accent
line--bs-lineDividers and outlines
font--bs-fontBody and UI type
radius--bs-radiusCorner radius
voiceFont--bs-voice-fontOptional second family for promise lines

Two more are derived: --bs-accent-soft and --bs-line-soft, light tints for highlights and dividers.

Modes

mode="light" and mode="dark" pin a mode. mode="system" follows the reader's setting through prefers-color-scheme.

Contrast

The Brand Studio contract check fails a palette when ink, muted text or text on the accent falls under 4.5:1 against its background. Run it before you ship a palette:

npm run check:brand

Your own components

Read the same variables in your CSS and your components follow the brand too:

.promo {
  background: var(--bs-elevated);
  border: 1px solid var(--bs-line);
  border-radius: var(--bs-radius);
  color: var(--bs-ink);
}

Still, Deskhand and Hollis are fictional brands. The coffee photographs are original generated artwork. @brand-studio/ui is MIT licensed.