What are tokens?
Design system tokens are the smallest, repeatable units of a design system. They're essentially named variables that represent a single design decision, such as a color, font size, spacing value, or animation duration. Instead of using hard-coded values like #FFFFFF or 16px directly in design files and code, you use a token name like color-background-primary or spacing-md.
Design systems use them for a few key reasons:
- Consistency and Single Source of Truth: Tokens act as a single source of truth for all design decisions. By using tokens, you ensure that every part of a product—from a button to a text field—is using the same, consistent style. If a color needs to be updated, you only need to change it in one place (the token's value), and that change automatically propagates to every component that uses it.
- Efficiency and Scalability: They make it much faster and easier to build, maintain, and scale products. Designers and developers can work with a shared, descriptive language, which streamlines the handoff process and reduces the time spent on manual style adjustments. This is especially crucial for large-scale projects or multi-brand platforms that may require different themes (like light and dark modes).
- Platform Agnosticism: Tokens are stored in a platform-agnostic format, typically a JSON file. This means the same design decisions can be translated into native code for iOS, Android, and web platforms, ensuring a consistent user experience across different devices.
- Improved Communication: Tokens create a shared vocabulary between designers and developers. Instead of describing a visual element by its specific properties, they can simply refer to the token, which already contains all the necessary information.
Usage
You should avoid accessing tokens directly in most cases. When using a pre-built component, like one from the Watson design system, there's no need to access tokens, as they are already built into the components themselves. This helps maintain consistency and the integrity of the design system.
When to access tokens directly:
- Creating custom components that are visually aligned to the Docplanner's brand styles
- Creating new components that can be contributed back to the system
- Creating a unique layout that requires specific spacing or sizing
- Adding a style exception for a specific use case that isn't covered by an existing component
- There are technical limitations to consuming components
- For example, PMSs can access tokens to visually look aligned to Watson
When to avoid direct token access:
- Using a pre-built component from Watson. These already have tokens built into their code. Overriding these with direct token access can lead to inconsistent styling and make the component harder to maintain.
- Changing styles of an existing component. If a style needs to be changed, use the props or variations provided by the design system, rather than trying to apply tokens directly.
- For example, if you need a secondary button, use the variant="secondary" prop instead of directly applying the color-background-secondary token.
-
Applying tokens directly for a single, unique use case can create an exception to the system's rules. This can lead to what is sometimes called "token creep," where the number of unique tokens becomes unmanageable.
Naming Structures
Tokens follow a consistent naming convention build with segments. Each segment has a defined purpose. Depending on the tier, the relevant segments are used. Segments are arranged from least specific to most specific.
Core tokens
Core tokens store raw, low-level design primitives and do not carry a design decision. They are abstract and serve as the foundation from which semantic tokens are mapped. Their names include:
- Type: type of value (e.g, color, font-size, spacing).
- Variant(s): defines the family within a type, e.g. Gray, Blue, or Serif.
- Scale: the step within a variant’s range.
Examples of core tokens
- color-blue-600
- font-size-xl
-
space-8
Semantic tokens
Semantic tokens capture design intent rather than raw values. They are value-agnostic and communicate what a token means in the system. Their names are composed of segments that describe:
- Type: type of value (e.g, Color, Font-size, Space).
- Role: the high-level concept the token represents (Background, Heading, Border)
- Variant(s): qualifiers that specify intent or nuance (Primary, Inverted, Emphasis).
- Variants are often unique to a specific token group.
- Scale: when a role is expressed in multiple sizes/levels (xs, lg, Condensed).
- State: if the token applies to an interaction state (Hover, Active, Disabled).
- Viewport: if values differ by platform or breakpoint.
Examples of semantic tokens
- color-background-primary-hover
- font-size-section-heading
- space-xl
Component tokens
Component tokens describe the choice of values for a specific component, not the abstract intent. They answer “what value does this part of the component use?” rather than “what is the meaning of this value?”. Their purpose is to tie semantic decisions back to UI elements.
A component token name is composed of the following segments:
- Component — the component the token belongs to (Button, Card, Input).
- Variant: the version of the component (Primary, Secondary, Success, Compact).
- Element: the specific part inside the component (Label, Icon).
- Type: the property being applied (Color, Font-size, Padding, Border-radius).
- Role: optional refinement of the type (Foreground, Background, Border).
- State: if the token applies to an interaction state (Hover, Focus, Disabled).
- Viewport: if values differ by platform or breakpoint.
Examples of component tokens:
button-label-font-size
button-primary-color-background
button-gap