Skip to content
Becoming a design system designer

Part 02 of 14 · · 4 min read

Design tokens: three tiers, clear names, one source of truth

What design tokens are, why the semantic tier matters most, how to name them, how to build them in Figma Variables and how they reach code as CSS.

A design token is a design decision with a name. Instead of writing #1B1F2A into a file, you write color.text.primary, and that name points to the value. Design files and code both read the same names, so a change made once shows up everywhere.

Tokens sound like a developer detail, but they are where a design system starts to pay for itself. They turn “use the dark grey for body text” from a habit into a rule that tools can check.

The three tiers

Most mature systems split tokens into three tiers. Each tier points to the one above it, never the other way round.

TierExampleWhat it does
Primitive (global)blue-600 = #2563EB, space-4 = 16pxThe raw palette and scales. Components never use these directly
Semantic (alias)color.bg.brand → blue-600, color.text.danger → red-600Names the intent. When a theme changes, this is the tier that changes
Componentbutton.primary.bg → color.bg.brandBelongs to one component. Add one only when a component needs it, not for everything

Why the semantic tier matters most

Take dark mode. The colour blue-600 does not change in dark mode; it is still the same blue. What changes is which primitive color.bg.brand points to. In light mode it might be blue-600, in dark mode a lighter blue-400.

Because every component uses color.bg.brand and not the primitive, no component needs editing. You change the mapping in one place and the whole interface follows. The same trick handles a second brand, a high-contrast theme or a denser layout.

If components reach straight for primitives, a theme change means hunting through every component by hand. That is the problem tokens were meant to solve.

Naming tokens

A common structure is category, property, role, state, read from general to specific:

text

color.text.primary
color.text.secondary
color.bg.surface
color.bg.surface.hover
color.border.danger
space.inset.md          padding inside a container
space.stack.lg          vertical gap between items
radius.md
shadow.overlay
font.size.body-md
motion.duration.fast
motion.easing.standard

Two rules keep names useful over time:

  • Name the purpose, not the look. color.text.danger survives a rebrand. color.red-text becomes a lie the day the brand’s red turns orange.
  • Pick one scale style and keep it. T-shirt sizes (sm, md, lg) or numeric steps (100 to 900) both work. Mixing them in one system does not.

What gets a token

  • Colour: text, background and surface, border, icon, interactive states and feedback (success, warning, danger, info).
  • Typography: family, size, weight, line height and letter spacing, often grouped into a composite text style.
  • Spacing: usually a 4px base, such as 0, 2, 4, 8, 12, 16, 24, 32, 48, 64.
  • Sizing: icon sizes and control heights, for example 32, 40 and 48.
  • Radius and border width.
  • Elevation: shadows and z-index layers.
  • Motion: durations and easing curves.
  • Breakpoints.

Building tokens with Figma Variables

Figma’s native way to store tokens is Variables. They come in four types: colour, number, string and boolean. A clean setup looks like this:

  1. Make separate collections: Primitives, Semantic, and Component only if you need it.
  2. Hide primitives from publishing, so designers using the library cannot pick a raw value by mistake.
  3. Add modes to the semantic collection, such as Light and Dark. Each semantic variable aliases a primitive in each mode.
  4. Set scoping. Limit color.text.* to text fills so it never shows up as a frame background. Fewer choices, fewer mistakes.
  5. Fill in code syntax. Add the web name, for example var(--color-text-primary), and developers see it directly in Dev Mode.
  6. Bind number variables to padding, gap and radius in Auto Layout, so spacing comes from the scale too.

Modes are not only for dark mode

A mode can hold any set of alternatives: density (compact and comfortable), brand (product A and product B), breakpoint (mobile and desktop type sizes), even language for string variables.

From design to code

The W3C Design Tokens Community Group publishes a standard JSON format, so tools can exchange tokens without custom glue. Each token has a $type and a $value, and an alias points to another token with curly braces:

json

{
  "color": {
    "blue": {
      "600": {
        "$type": "color",
        "$value": { "colorSpace": "srgb", "components": [0.145, 0.388, 0.922], "hex": "#2563EB" }
      }
    },
    "bg": {
      "brand": { "$type": "color", "$value": "{color.blue.600}" }
    }
  },
  "space": {
    "4": { "$type": "dimension", "$value": { "value": 16, "unit": "px" } }
  }
}
A primitive, a semantic alias and a spacing token in the DTCG format

A typical pipeline keeps that file in Git and builds every platform from it:

text

Figma Variables
   │  export (Tokens Studio, the Figma REST API or a plugin)
   ▼
tokens.json in a Git repository
   │  build (Style Dictionary)
   ▼
CSS variables · Tailwind theme · iOS and Android values

The web output is plain CSS custom properties. A theme only redefines the semantic values:

css

:root {
  --color-bg-brand: #2563EB;
  --color-text-primary: #1B1F2A;
  --space-4: 16px;
}

[data-theme="dark"] {
  --color-bg-brand: #60A5FA;
  --color-text-primary: #F1F3F8;
}

This is what people mean by a single source of truth: one token file, and Figma and code both follow it. When a value changes, it changes in the file, and both sides pick it up.

Try this

Open any interface you use daily and list ten colours you can see. Give each one a semantic name, such as color.text.secondary or color.border.subtle, then map it to a primitive. Now write a dark mode: change only the mappings, not the names. If a name stops making sense in dark mode, it was describing the look, not the purpose.

Next in the series

Tokens live in Figma as variables, but they only pay off when the file around them is built well. Part 3 covers the Figma skills a design system depends on: Auto Layout, components and variants, properties, and how to organise and publish a library.

Sources and further reading

See a design system in practice: the AppsCode Design System case study