Skip to main content
Design Systems

Design tokens are not enough

March 20, 2026 · 4 min read


What tokens get right

Design tokens are a genuine improvement over hardcoded values. When spacing-md is defined as 16px and automatically translated to space-4 in Tailwind, 1rem in CSS, .padding(16) in SwiftUI, and 16.dp in Jetpack Compose, you have solved the translation problem. Designers and developers share the same named value, even across different implementation contexts.

The token layer — particularly when paired with a platform that handles the translation automatically — removes an entire class of divergence. The conversation is no longer 'which pixel value do you mean?' It is 'which token do you mean?'

What tokens miss

But tokens tell you what values exist. They do not tell you which value to use, where, and why.

Take spacing-md = 16px. Your component library might use this token for: the padding inside a Button, the gap between a label and its input field, the margin between list items, the padding inside a card, and the gap between form sections. These are five different uses of the same value — and they are not interchangeable.

If a designer decides that the gap between a label and its input should be tightened to spacing-xs for compact forms, that decision needs to be captured somewhere. The token definition does not contain it. The translation layer does not contain it. It exists, if it exists at all, in a Figma annotation that a developer may or may not see.

Tokens define the vocabulary. Contracts define the grammar — how words are put together, and why.

The semantic layer

The missing layer is semantic: the connection between a token and its intended use in a specific context. This is not something that can be expressed in a token file. It requires a component contract.

A contract for an Input component might specify: the gap between the label and the input field uses spacing-xs (8px). The padding inside the input field uses spacing-sm (12px) vertical and spacing-md (16px) horizontal. The error message below the field uses spacing-xs top margin. These are not just token values — they are commitments about where and how those values are applied.

Why this matters at scale

In a small design system with a handful of components, the semantic layer can live in people's heads or in informal documentation. As the system grows, this breaks down. Developers make pragmatic substitutions — spacing-sm instead of spacing-xs — without knowing they have deviated from the specification. Designers iterate without tracking which components are affected by a token change.

At scale, you need the semantic layer to be explicit, verifiable, and connected to the components that reference it. That is what a contract provides: a named, versioned agreement that says this component uses this token in this context, and any deviation from that agreement is a divergence — not a choice.

Tokens and contracts together

Design tokens and component contracts are complementary, not competing. Tokens define the available values. Contracts define the intended usage. Together, they create a complete specification: a designer can express not just what values exist, but how they should be composed into components — and that specification can be validated automatically at every stage of the design and development workflow.

← Back to blog