Design tokens: decisions with a name
It is easy to reduce design tokens to a technical detail: variables that hold colors and sizes. But that reading misses the point. A token is a design decision with a stable name.
The difference is in the name. #1a1a1a is data. color-text-primary is a decision: this is the color we use to speak to the user in the foreground. The value can change; the decision stays.
Three layers, three responsibilities
A healthy token system is usually organized in layers, and each one answers a different question:
- Primitives — what values exist? A raw palette:
gray-900,blue-500,space-4. They mean nothing on their own. - Semantic — what do they mean?
color-text-primary,color-surface,space-inset. This is where intent lives. - Component — how are they applied here?
button-background,card-padding. They tie intent to a specific context.
The rule that keeps everything in order is simple: a layer may only refer to the previous one. Components never point at a primitive directly.
The real benefit: the dark mode you didn’t design twice
When components consume semantic tokens, dark mode stops being a redesign and becomes a remap:
:root {
--color-surface: #ffffff;
--color-text-primary: #1a1a1a;
}
@media (prefers-color-scheme: dark) {
:root {
--color-surface: #101010;
--color-text-primary: #e9e9e7;
}
}
No component changed. What changed is what its decisions mean in a different context. That is a token doing its job: absorbing change so nothing else has to know about it.