Blog

Design Tokens in React: A Practical Guide to Scalable Theming

Learn how to use design tokens in React for scalable themes, semantic colors, spacing, typography, component states, and dark mode.

ReactDesign TokensThemingDesign Systems

Design tokens give React teams a shared vocabulary for visual decisions. Instead of repeating a hex value, spacing number, or shadow in many components, the team names the decision once and reuses it throughout the interface.

Tokens are not valuable merely because values live in variables. Their value comes from expressing intent, creating consistency, and making coordinated changes safer.

This guide focuses specifically on token architecture and runtime theme mapping. If your main challenge is adapting a third-party library without creating a fork, read the broader component-library customization strategy.

Start with a small foundation

A token system does not need hundreds of values on its first day. Begin with the decisions already repeated in the product:

  • Brand and neutral color scales.
  • Background, surface, text, and border roles.
  • Spacing steps.
  • Font families, sizes, weights, and line heights.
  • Border radii.
  • Border widths.
  • Elevation and shadows.
  • Motion durations and easing.

Keep the initial scale understandable. Extra values that have no clear use make the system harder to follow and encourage arbitrary choices.

Separate raw values from semantic meaning

Primitive tokens name a position in a scale, such as blue-600 or space-4. Semantic tokens describe how the value is used, such as color-action-primary or space-control-inline.

That distinction makes themes easier to change:

:root {
  --blue-600: #2563eb;
  --blue-300: #93c5fd;
  --color-action-primary: var(--blue-600);
  --color-focus-ring: var(--blue-300);
}

Components should usually consume semantic tokens. If every button references blue-600 directly, changing the primary brand role requires editing component styles rather than updating the theme mapping.

Model surfaces and text together

Themes are relationships between values. A background color is not complete without text, border, focus, and interactive states that remain readable on it.

Define paired roles such as:

  • Page background and default text.
  • Raised surface and surface text.
  • Primary action and action text.
  • Muted surface and secondary text.
  • Error surface, error border, and error text.

This approach is especially important for dark themes. Inverting a few colors rarely produces a coherent, accessible result.

Use CSS variables at runtime

CSS variables work well for React theming because the browser can resolve them without rerendering every component. A theme can set variables on the document or on a smaller container.

[data-color-scheme="night"] {
  --color-background: #0f172a;
  --color-surface: #172033;
  --color-text: #f8fafc;
  --color-action-primary: #60a5fa;
}

React can select the theme by changing an attribute, while component CSS continues to use semantic variables.

Scoped themes are useful for previews, embedded tools, dashboards, or multi-brand applications. Two parts of a page can inherit different token mappings without duplicating component code.

Resolve the initial theme before hydration

In a server-rendered React or Next.js application, the first HTML response should know which theme to display whenever possible. Waiting for a client effect can produce a flash from the default theme to the saved theme.

Persist the selection in a location the server can read, such as a cookie, or use a small pre-hydration script when system preference must be resolved in the browser. Keep the server HTML and first client render aligned to avoid hydration warnings.

The Boreal UI guide to theming without flashes covers this lifecycle in more detail.

Add component-level tokens selectively

Global semantic tokens should handle most styling. Component tokens are useful when a component has a stable internal concept that needs controlled customization.

A button might use:

  • --button-background
  • --button-text
  • --button-border
  • --button-radius
  • --button-padding-inline

Avoid exposing a variable for every CSS declaration. Too many component tokens turn the public styling API into a mirror of the implementation and make future refactoring difficult.

Include interaction and status states

A token system must cover more than the default screenshot. Define hover, active, selected, disabled, focus, loading, success, warning, and error roles.

Do not communicate status with color alone. Components still need text, icons, semantics, and accessible names where appropriate. Tokens help states look consistent; they do not provide the behavior by themselves.

Connect design and code vocabulary

Tokens are most effective when designers and developers use the same names. If a design file says “surface/subtle” while code says grayBackgroundSecondary, the mapping becomes tribal knowledge.

Document each semantic token with:

  • Its purpose.
  • Where it should and should not be used.
  • Its light and dark values.
  • Relevant contrast requirements.
  • Components that consume it.

This documentation turns the token set into a decision system rather than a long variable list.

Test themes as complete systems

Create a page containing text, links, buttons, inputs, overlays, feedback states, and data visualization. Review every supported theme on that page.

Check contrast, focus visibility, disabled-state clarity, long content, zoom, and reduced-motion preferences. Automated contrast checks can catch many issues, but human review is still needed to judge hierarchy and readability.

Evolve tokens without breaking consumers

Treat public tokens like an API. Renaming or removing a token can break consumer styles just as changing a React prop can break TypeScript code.

When a token must change, provide an alias or documented migration period. Remove unused values deliberately instead of allowing the system to accumulate near-duplicates.

Boreal UI combines SCSS variables, runtime CSS variables, and named color schemes. Explore the theming overview, token reference, and scheme designer to see how these layers work together.