Building better products with the design token pipeline

Last iteration • 
Design Token Pipeline

You may know what design tokens are and what benefits they can bring. But you may wonder how exactly to start using them and how you can integrate them into your workflow. I this article you will learn just that:

Improve your design with design tokens

Design tokens are an integral part of any design system. They bridge the gap between core values (brand colors, typography, etc.) and components. But before we look into how they help, let's have a look at the problem we are trying to solve.

Problem

Design Systems often live within design tools as component libraries. Maybe there is a code component library so developers can work with components as well.

Component libraries are certainly helpful to quickly put together products. But those components don’t tell the entire story. The decision of what value to use where, has already been made. It is buried within the component, not apparent to the component user. When components are your smallest unit, it is hard to know how to build a new component that fits into the system.

You don't know why the notification is blue or why the primary button is green.
And you don't know how to make sure new components update when the design system changes.

In short, while components are great to use, they are:

Solutions

Enter: “Design tokens”. They come in two varieties: options and decisions and solve can solve the problems I mentioned above.

Design tokens option to decision

Option Design Token

Option design tokens represent ALL available values within your design system. All colors, font sizes and spacings should be represented as an option design token.

The option token definition is the only place where raw values like 8px are allowed.

Option design tokens should not be used directly but only referenced by decision design tokens.

An option design tokens name is an abstract representation of its value. It does not suggest any use:

With all options at hand, fitting new components into the design system gets much easier. Just pick and choose which of the available option design tokens fits best. Creating and using decision design tokens that reference option design tokens have another benefit. Your components update automatically when the options change.

Decision Design Tokens

Decision design tokens represent a context in which a referenced value is used.
They never hold a raw value (e.g. 8px), but only ever reference an option design token like $color-blue-500.

The name of a decision design tokens represents how and in what context to use the token.

Following this approach your token names are a small part of your documentation. Token users (mostly developers) can understand what the intended use of a token is.

This prevents them from mixing up values and allows them to flag missing / misused tokens.

Additionally, using decision design tokens allows you to restrict changes to a context. You can change the background of the CTA-button on your landing page, without influencing the rest of the product.

This allows for a good balance between consistency / maintainability and flexibility.

Documentation & storage

Design tokens live in a technology agnostic file (like json or yaml), stored in a central location accessible by all teams. This lifts them out of your design file and into the middle of the product development process. Design tokens "belong" to everyone, they are a tool that all can and should use.

The token file is meant for everyone, so adding documentation is encouraged. This is best done by adding a comment, description or remarks property to a token. As of now there is no standard for how to name it.

documenting design tokens
'colors': {
  // ...
  'danger-red' : {
    'value': '#F52C10',
    // depending on your toolset any of the below may be supported
    // otherwise they are normally ignored and should not create an error
    'comment': 'This color is only use for error messages',
    'description': 'This color is only use for error messages',
    'remarks': 'This color is only use for error messages',
    'deprecated': 'This color is deprecated, use core-red instead'
  }
}

This can be helpful to mark tokens as deprecated or experimental. You can also add usage info that elaborates on the info provided by the name. E.g. This color may only be used for error messages.

Conclusion

Specifying and documenting with design tokens

Working with a design system most of your work is composing components into layouts. At this point most of the documentation work has already been done. You only need to specify the spaces around the components, if this is not done on a per component level.

Design Tokens specs around components

Building components

If you are building new components, you have the responsibility of documenting them. This means adding descriptions, but also defining good names for the decision design tokens.

Caveat

Since (most) design tools don’t support design tokens (yet), you can't ask developers to use the "inspect" feature. But then again, hoping that all developers check your files may not be the best idea to begin with. They are busy as well.

Instead you need to go old-school and create visual specifications. This allows you to add the decision design tokens as well as any additional documentation.

While this is tedious work and hopefully will be automated soon, it has an upside. While specifying components you double-check that they are built correctly. While using a wrong text style may happen, adding the wrong decision token is far less likely.

Button

Design Token Specs for Button

A button may have a label, a background color, a corner radius, padding and a shadow. For this you would create the following decision tokens:

Button component
$button-label-color: $text-on-light
$button-label-font-size: $typescale-md
$button-background-color: $color-neutral-100
$button-corner-radius: $corner-radius-sm
$button-padding: $size-sm
$button-elevation: $elevation-500

Modal

A modal may hold content like a list or buttons. The component is the same though, no matter the content. It may have a background, corner radius, padding, elevation and a color for the overlay separating it from the page.

Modal component
$modal-background-color: $color-white
$modal-corner-radius: $corner-radius-xs
$modal-padding: $size-sm
$modal-elevation: $elevation-100
$modal-overlay-color: $color-neutral-700
$modal-overlay-opacity: $transparent-slightly

Benefits

Encapsulation

Decision tokens are strongly tied to a specific implementation e.g. a component. They are encapsulated, meaning changes will not affect anything outside of their context. This can save you a lot of trouble, especially if you have a huge design system.

Be careful though, this encapsulation is solely due to the naming convention & proper use of decision tokens.

Less mistakes

At some point there is a step where components have to move from a design tool into code. Developers often use the inspect mode to view the raw values the designer used for a component. This has always been a potential source for mistakes, due to two reasons. Either the designer has not worked tidy and some elements are a couple pixels off. Or the developer makes a mistake when transferring the values into her code.

Design tokens solve this. The tokens are already defined somewhere else by the designer. The can pull them in from a repository to have them available. Now the developer only needs to read the specs and add the tokens. Using a wrong token, like using $button-padding-top for the padding-bottom property is less likely than mixing up raw values. With tokens when reading the code it is visually apparent that something was mixed up, when you see the line:

Wrongly specified token
padding-bottom: $button-padding-top

Easy to maintain & theme

Using tokens means you can easily update your products by simply changing the tokens. This can come in handy in different situations.

Dark mode

Theming always reminds me of myspace but there is a very common use case: dark mode. It's so popular that even our operating systems have a dark mode. 

If you built your software using design tokens implementing dark mode may take no more than an afternoon.

To be well setup for dark mode your token inheritance chain should be like this:

  1. Option design tokens ($primary-color, $neutrals, ...)

  2. General decision tokens ($background-color: $white, $text-color-intense: $black )

  3. Component decision tokens ($modal-background-color: $background-color)

Now all you need to is change the general decision design tokens when dark mode is enabled.*

* Depending on the complexity of your app it may not be quite as easy, but the principle works.

Branding

Another common use case where design tokens shine is shared component libraries. When using the same component library for multiple sub-brands you are basically theming. 

In this case you can exchange the option tokens like the $primary-color and you are already 90% there.

Integrating design tokens into the development pipeline

One of the promises of design tokens is to extract design decisions into a central location. The benefit is, that decisions can be changed in one place and the entire system updates.

For this to work, the design tokens have to be integrated into the development pipeline. You have to do it in a way that allows for "automatic" updates. Before we look deeper into this, let's examine the old way and the related problems.

How we used to do it

  1. On every platform we created files to store variables holding raw values. They look like design tokens, e.g. $main-color: #228912.

  2. We used the variables throughout the application. 

  3. When a raw value changed, the developers on every platform updated their files.

This seems fine at first, but it has some issues:

Doing it the design token way

  1. The designers create/export design tokens 

    1. Tokens are exported in a platform agnostic format (e.g. json or yaml) in a central location (e.g. design tokens repo) 

    2. Tokens are automatically converted to be usable by all platforms

  2. Tokens are imported using npm, a git subdirectory or something similar

  3. Tokens are used throughout the applications

  4. During the build process dependencies are checked for updates. If and update for the tokens is available an error is thrown* 

  5. When raw values change, the tokens repository is updated

  6. Developers will notice the update by their build failing

In both cases slack channels, dailies and other ways may be used to inform about design token updates. The failing built should not be the first, but the last way a developer finds out about changes.

This process solves all the above mentioned issues:

*Additional notes

The workflow above is a bit simplified. You should still allow builds by supplying an --ignore-dep-warning argument. This is necessary for hotfixes, etc. 

You may also decide to only fail on patches and minor updates to the design tokens. Major updates (1.X.X → 2.0.0) may need some time to implement.

Figma Design Token Plugin Cover

I created a plugin for Figma that lets you automatically sync your design tokens with a repository so that the latest version is always available to your team.

Try it now →

Summary