UIGuides

Design Tokens Explained: What They Are and How to Use Them

5 min read

Learn what design tokens are, the difference between primitive and semantic tokens, and how to set up a token chain from Figma Variables to code.

Design tokens are one of those concepts that sounds abstract until you've worked without them and then had to update a brand color across 47 screens in Figma while also asking the dev team to do the same in their codebase. Then they become obvious.

Here's what they are and how to use them practically.

What design tokens actually are

A design token is a design decision stored as a named variable. Instead of hardcoding #1D4ED8 everywhere you use your primary blue, you store that value as color.blue.600 and reference that name wherever the color is needed.

The name is the token. The value can change. Everything that references the token updates automatically.

This matters because your product exists in multiple places — Figma files, a React codebase, an iOS app, an Android app, a marketing site. Design tokens give all of those a shared language.

Types of tokens

Tokens cover every repeatable design decision:

  • Color — hex values, opacity levels
  • Spacing — 4px, 8px, 12px, 16px, 24px, 32px, 48px, 64px...
  • Typography — font family, font size, font weight, line height, letter spacing
  • Shadow — box shadow values
  • Border radius — 0px, 4px, 8px, 16px, 9999px (pill)
  • Duration — animation timing (150ms, 300ms, 500ms)

If you're making the same visual decision repeatedly, it should be a token.

Primitive tokens vs semantic tokens

This is the distinction most teams miss, and it's the one that makes tokens actually scalable.

Primitive tokens are raw values with no context attached:

  • color.blue.600 = #1D4ED8
  • color.gray.100 = #F3F4F6
  • spacing.4 = 16px

Semantic tokens describe the purpose of a value, and they reference primitive tokens rather than raw values:

  • color.background.primary = color.blue.600
  • color.background.surface = color.gray.100
  • color.text.default = color.gray.900

Why do you need both? Because semantic tokens let you change a theme without changing every component. To support dark mode, you only update the semantic token mappings — color.background.surface points to color.gray.900 in dark mode instead of color.gray.100. Every component that uses color.background.surface updates automatically. No hunting through components.

How tokens flow from design to code

The ideal flow looks like this:

  1. You define tokens in Figma using Variables (Figma's native token system since mid-2023)
  2. Tokens get exported to a JSON format using the Tokens Studio plugin or a custom Figma plugin
  3. That JSON gets fed into a style processor like Style Dictionary
  4. Style Dictionary outputs platform-specific formats: CSS custom properties for web, Swift constants for iOS, Kotlin values for Android

In practice, many teams skip the Style Dictionary step and just maintain tokens in Figma and in CSS manually. That's fine for small teams. At scale, the automated pipeline pays for itself.

Tools for managing tokens

Figma Variables is the native solution, built into Figma since 2023. You can create color, number, string, and boolean variables. It supports modes (useful for light/dark theming). It's the right place to start.

Tokens Studio (a Figma plugin) extends Figma Variables with more token types and better JSON export. Good if you need the design-to-code pipeline.

Style Dictionary is an open-source build system from Amazon. It transforms your token JSON into any format you need. It's a developer tool, but designers should know it exists.

Zeroheight lets you document your tokens alongside components so your team can find and use them without needing to dig through Figma.

Try Zeroheight Free

A real example: the button token chain

Here's how a primary button's background color flows through a token system:

Primitive: color.blue.600 = #2563EB

Semantic: color.interactive.primary = color.blue.600

Component: button.background.default = color.interactive.primary

When you want to change your brand color from blue to purple, you update color.blue.600's value and swap color.interactive.primary to reference color.purple.600. Every button, every link, every badge that uses color.interactive.primary updates in one change.

The same button has tokens for:

  • button.background.hover = color.blue.700
  • button.background.disabled = color.gray.200
  • button.text.default = color.white
  • button.text.disabled = color.gray.400
  • button.border.radius = border.radius.md
  • button.padding.horizontal = spacing.4
  • button.padding.vertical = spacing.2

That's the full token chain for one component. Multiply that across a design system with 50 components and you understand why the naming structure matters.

Where to start

If you're setting up tokens for the first time:

  1. Start with color — it has the most immediate impact
  2. Create your primitive color scale (10 shades per hue)
  3. Map semantic roles on top (primary, surface, text, error, success, warning, info)
  4. Add spacing next (use a 4px base unit)
  5. Add typography last

Don't try to tokenize everything at once. A working color and spacing token system is more valuable than a theoretically complete system you never shipped.

Try Storybook Free

Storybook is where these tokens often get documented on the code side — each component story shows the token values in use, creating a living reference for developers.