AniUI Academy

Theming and Design Tokens

Design tokens as the layer that separates a design decision from where it's used, and how that separation is what makes theming, dark mode and rebrands tractable.

10 min read

A rebrand, a new theme, or dark mode support should not require touching every component in a design system one at a time. That they don't have to is entirely because of one architectural decision: design tokens, which separate what a design decision is from where it's used.

What a token actually is

A token is a named, indirect reference to a design value — a color, a spacing unit, a font size, a border radius — rather than the raw value itself, used directly at every place it's needed:

// Without tokens: the same raw value, copy-pasted everywhere it's needed.
// button.css
color: #3B82F6;
// link.css
color: #3B82F6;
 
// With tokens: one definition, referenced everywhere.
const tokens = {
  color: {
    primary: "#3B82F6",
  },
};
// button.css and link.css both reference tokens.color.primary

The value isn't the naming itself — it's that the actual value now lives in exactly one place. Changing tokens.color.primary once propagates to every component that referenced it, with zero changes required in those components. Compare that to hard-coded values: updating a brand color means finding every literal occurrence of that hex value across the codebase, which is exactly the kind of task that's easy to almost get right and hard to get completely right.

Semantic tokens: the layer that makes theming actually work

The deeper payoff comes from a second level of indirection: semantic tokens, named for their role rather than their literal value — color.background, color.text.primary, color.border.danger — which themselves reference the raw value tokens.

Raw value tokens

The actual values — a specific blue hex code, a specific spacing number. Rarely referenced directly by components.

Semantic tokens

Named for role, not value — color.background, color.text.primary. Components reference these, not raw values.

Components

Reference only semantic tokens. Never hard-code a raw value or know which theme is currently active.

Components should reference only semantic tokens, and should have no awareness of whether light or dark mode (or any other theme) is currently active. Dark mode, then, is implemented once, at the token layer: define what color.background and color.text.primary resolve to for a dark theme, and every component that already referenced those semantic tokens picks up the new values automatically — with literally zero changes to any component's own code, precisely because none of them ever hard-coded a raw value or branched on the active theme themselves.

Where tokens actually live and how they reach code

In practice, tokens are usually authored once, often in a format like the W3C Design Tokens spec or a tool like Style Dictionary, and then compiled into whatever a given platform actually consumes — CSS custom properties for the web, a Swift/Kotlin constants file for native platforms, a Figma variables collection for designers working in the design tool itself. This is what lets a single design decision — "the brand's primary color is changing" — update consistently across web, native apps, and design mockups from one source of truth, rather than three separately maintained copies inevitably drifting out of sync with each other over time.

The discipline this requires from component authors

None of this works if component authors quietly reach for a raw value "just this once" because the right semantic token doesn't quite exist yet — that one hard-coded value is invisible to the token system entirely, and silently won't update the next time a rebrand or theme change happens. The actual discipline design tokens require is refusing that shortcut: if the right semantic token doesn't exist, that's a signal to add one (a genuine gap in the token vocabulary), not a license to hard-code a value locally and lose the entire benefit for that one spot.

What to remember

  • A token is a named, indirect reference to a design value — the actual value lives in one place, and everywhere that references the token updates automatically when it changes.
  • Semantic tokens (named for role — background, text, border — not literal value) are what components should reference, never raw values directly.
  • Dark mode and rebrands become single, centralized changes at the token layer, with zero changes to component code, as long as components never hard-code raw values.
  • A hard-coded value anywhere in a component is invisible to the token system and will silently fail to update on the next theme change — treat that as a missing token, not an acceptable shortcut.

Check yourself

3 questions · pass 3/3 to unlock How to Approach a Frontend System Design Interview

up to 50
  1. 1.A component library hard-codes color: #3B82F6 directly inside dozens of components wherever the brand's primary blue is needed. What problem does this cause when the brand color changes?

  2. 2.What is a design token, and what does referencing color.primary instead of a raw hex value actually buy you?

  3. 3.How do design tokens make dark mode tractable, compared to writing separate dark-mode styles for every component individually?

3 left to answer