Design Tokens and Theming
Learn to architect design tokens and theming as first-class render inputs, building scalable light/dark modes and theme variants without visual drift or component-level conditionals.
We'll cover the following...
- Design tokens as a semantic interface for theming
- Example: Switching themes without component-level conditionals
- Advanced optimization: Keeping token updates cheap, theme switches coherent, and identity consistent at scale
- Practice exercises.
- Exercise 2: Add a scalable “brand” variant without changing components
In the early stages of a React application, styling decisions feel harmless. A color is copied from a design file. A spacing value is hardcoded into a component. A border radius is chosen just for this card. Light mode works, so we move on. As the product evolves, those small decisions accumulate. Multiple teams introduce slightly different shades of the same gray. Buttons across different screens have inconsistent hover states. Some components respond correctly to dark mode; others forget to adjust text contrast. A new brand campaign requires a visual variant, so developers add if (theme === "dark") logic inside components. Over time, styling logic spreads across the tree, and visual identity becomes fragile.
Now add scale. Design introduces a high-contrast accessibility mode. Marketing wants seasonal theming. Product wants white-label brand variants for enterprise clients. Suddenly, visual styling is not just decoration; it is a system requirement. And when themes switch, the entire application must update coherently without layout shifts, inconsistent tokens, or duplicated logic. The underlying problem is architectural drift. Components depend directly on literal values rather than on semantic meaning. There is no single source of truth for design decisions. Themes are applied imperatively or inconsistently. When the theme changes, the update is not atomic; it is scattered.
In React 19, where rendering is concurrent and boundary-based, a theme switch is effectively a full visual re-render under a new design contract. If tokens are not centralized and themes are not modeled as controlled render inputs, concurrency can expose visual inconsistencies: partial updates, stale values, and mismatched surfaces. The problem we are solving in this lesson is therefore deeper than “how to toggle dark mode.” We are designing a token-based styling architecture where:
Components depend on semantic tokens, not raw values
Themes define token mappings
Theme switching becomes a controlled render boundary
Visual identity remains consistent as the system scales
At the top sits the Active Theme (
Light,Dark, or aBrandvariant). This theme supplies concrete values for semantic tokens, such ascolor.surfacemapping to#ffffffin light mode or#121212in dark mode,color.primarymapping to a brand color like#4f46e5, andspacing.mediummapping to16px.In the middle is the Token Layer, which defines the stable semantic interface: roles like
surface,primary,muted text,spacing.small, andradius.medium.At the bottom is the Component Tree, where components request styling by role instead of raw values: a
Cardusescolor.surface, aButtonusescolor.primary, and layout primitives usespacing.medium. When the theme switches, only the top layer changes. The token interface stays stable, components do not change, and React re-renders the tree under the new token mapping in a single, predictable update.
Design tokens as a semantic interface for theming
Design tokens represent semantic intent, not raw values. A token is not #121212. It is color.surface. It is not 16px. It is spacing.medium. This indirection is what allows the system to scale. When components use semantic tokens, they describe what they need, not how it is implemented.
The first architectural layer is the token definition. Tokens are structured by category, such as
color, ...