Design tokens have revolutionized the approach to digital product design by providing a scalable and efficient solution for maintaining visual consistency.
However, as design systems evolve, a challenge arises, known as the context dilemma. This refers to the need to provide flexibility while maintaining consistency across different contexts.
In this article, I will explore this dilemma using examples and discuss how balancing semantic and specific design tokens offers a robust solution.
Reflecting purpose
Design tokens offer a robust foundation for visual attributes, but applying them uniformly across all contexts may lead to inconsistencies.
Let's say we are defining design tokens for colors, giving some classic semantic names to reflect the meaning of each color:
$color-background-inverse: #fff;
$color-border: #96A1B0;
$color-text-muted: #697684;
When creating components, we can utilize these tokens to establish color schemes for the various elements within them.
The selected names are highly effective when it comes to a default button:
However, when it comes to a different component, the same names may not reflect the purpose of the color even though the color palette stays the same:
Progress bar consumes the color-text-muted
token for the forward line and color-border
for the backward.
When the context changes, using the same names can be confusing and make the component styles fragile. But how truly flexible are they?
Being semantic is hard
Using the right words to describe the semantic meaning of design tokens is crucial for ensuring that they are clear and consistent across various components.
This is particularly important when dealing with complex interfaces that require a high degree of consistency to function effectively.
Let’s try to generalize the names of the tokens:
Instead of differentiating them on their usage context (using "text" and "border" as words), we could achieve a more simplistic but flexible result by replacing them with "secondary".
Two possible strategies
In this scenario, I see two possible ways to proceed:
1. Context-specific semantic tokens
Given a group of global tokens, we could generate a large set of context-specific semantic tokens identifying common use cases.
$color-background-default: $color-white;
$color-background-primary: $color-blue;
$color-background-secondary: $color-gray-500;
$color-background-muted: $color-gray-300;
$color-border-default: $color-gray-100;
$color-border-primary: $color-blue;
$color-border-secondary: $color-gray-500;
$color-border-muted: $color-gray-300;
$color-text-default: $color-gray-900;
$color-text-primary: $color-blue;
$color-text-secondary: $color-gray-500;
$color-text-muted: $color-gray-300;
Repeating tokens for different contexts (e.g., using the same list for background, border, and text) is beneficial to ensure that designers and developers know which tokens are designed for each of them.
In the end, you’ll find that you can design an interface re-using almost all the semantic tokens.
As new or more particular components arise, go specific.
2. Start small and wait for patterns
Start with a small set of predictable semantic tokens and specific tokens for most components:
$color-primary: $color-blue;
$color-secondary: $color-gray-500;
$color-secondary-dark: $color-gray-800;
$color-secondary-light: $color-gray-300;
$color-secondary-light: $color-gray-100;
$color-inverse: $color-white;
We can apply this small set of tokens to our two components, avoiding excessive repetition. In this case, with two tokens we can cover all cases.
However, how much semantic value does the "secondary" label communicate?
How easy is it for a designer or developer to remember to use it correctly?
How to choose
As always in our profession, it depends. 🙂
In this case, the preminent variables are the Design system and interface complexity.
In my experience, creating context-specific semantic tokens works best for design systems of medium to high complexity, while the second option is better suited for small and simple ones.
Embrace the change
With design tokens, we are trying to create a global context for the whole interface we are building, including the no-known components of the future.
But this is an impossible mission. Covering all future needs it’s hard and design tokens aren’t set in stone.
We’d be prepared to embrace the change and, eventually, go specific.
As much as we have been good at imagining all possible uses of design tokens, there will always be a case where the choices made do not fit the real usage context.
Design Tokens Manager for Notion
A powerful template that helps you manage large sets of design tokens.