Using Design Tokens to Accelerate Design Systems

How Intuit is improving the developer UX for design tokens

Kelly Harrop
Intuit Design System (IDS)
7 min readMar 31, 2021

--

A rainbow-esque illustration that depicts a component being powered by themeable design tokens

As a unified design system, we empower teams across Intuit to deliver seamless, cohesive experiences.

Because we serve both designers and developers, we needed to invest in tooling that would allow us to scale our impact in order to fit their needs.

Opportunity: How could our team manage complex, evolving design data that would support multiple products and platforms?

We knew having a centralized data source for generating design tokens was the key to:

  • Making sweeping changes across multiple code repositories and design libraries
  • Seeing a bird’s eye view for what values were being used at both a foundational and component-specific level for each product
  • Creating closer parity between design and implementation

We also needed to account for the fact that not all teams are on the same tech stack and may have different requirements for implementation.

Design data management

Establishing a scalable system that could store design-related data was the first step in how we approached supporting our teams.

After reviewing a few options, we ended up choosing Style Dictionary, an open-source project from Amazon, which serves as a build system that generates design tokens.

From there, it was a matter of:

Style Dictionary’s charming chameleon logo
  • Defining architecture that would support our existing values
  • Adding audit logic to improve the stability of the system
  • Providing a visual representation of design tokens
  • Establishing logic to cascade data to match our system’s existing hierarchy & defaults

Contribution & Ownership

Creating the system was one thing, but making sure our team wasn’t a bottleneck was another. Keeping this in mind, we wanted to make sure the system was organized in a way so anyone could contribute towards their own product without introducing risk.

We did this by separating out our data into two main buckets:

  • Durable, foundational data that shouldn’t have overrides
  • Themeable data that could have overrides

Instead of a “restaurant” model where we would be taking orders, we encourage a “self-serve” model that enables teams to update their own data in their given theme folder.

Teams contribute data towards their own product theme within our centralized design data system

This approach makes our design data management system similar to an open source project, where users contribute the changes they need while having our team act as repo maintainers.

Teams make sure their data is accurate. We make sure the system doesn’t implode. Win-win.

Iterating and improving

While we had developed a system that could handle robust data, the system is only successful if users actually use the tokens it generates.

We started by implementing tokens within a single component repository, paying attention to details such as:

  • How do users know what tokens are available?
  • What changes to the repo should users be aware of?
  • Do they feel confident about which token to implement?

To facilitate adoption, our team was focused on ensuring we had created an easy experience for developers to implement design tokens.

From there, we could start onboarding more teams to the system and get feedback on improvements and learn of any gaps we needed to address.

Design token visibility

Since we don’t actually store the output of our build system in GitHub, we needed a way to surface what gets generated so users could see what our system was actually offering.

Storybook

We already leverage Storybook as a way to showcase our components as part of our Design Systems CLI, so it was the natural tool of choice to showcase our design tokens as well.

We’ve even created a custom Storybook addon that lets us define persistent theme and color mode data while users navigate different stories.

Our auto-generated Design Tokens Storybook

The experiment column highlights our intent of making sure that any team can add what they need and flagging the data as experimental, even if those values aren’t officially defined as part of our design system.

Using Storybook’s addon knobs, we can provide users the ability to filter tokens based on criteria we have defined using a combination of our architecture and custom Style Dictionary logic.

In addition to what’s shown in the screenshot, we’re also able to provide descriptions on the usage of the token. This is super helpful for informing teams on how the token should be implemented.

The best part of this setup is that it is completely automated and will update based on any changes to the repo. What you see is what you get!

Making changes with confidence

When updating design token values, it can be a little nerve-wracking since those changes could impact multiple components.

It can also be time-consuming to make design token updates, push those changes, and have to test in a separate component repo, only to find out you made a typo.

A link to a preview of our components as part of our CI

Our team solved this issue by creating a Storybook preview that showcased components using the canary release version of a pull request.

We typically use this feature to check that updating a token value wouldn’t visually break a component (and make our components better in the process!).

Mitigating risk

Semantic versions help inform teams on what to expect when they update their version of design tokens.

Auto

By using Auto, another Intuit open source project, we can easily associate our releases with what type of changes we’re making using GitHub labels:

  • patch: token values change
  • minor: new tokens added
  • major: token names changed/tokens deleted
Auto’s minimalist logo that features an odometer in the “O”

Because patch and minor versions introduce no breaking changes, teams have the ability to automatically consume the latest version by using ^ in their dependency settings if they’d like.

This enables teams to feel confident that no breaking changes will occur for non-major releases, and we can use a tool like Renovate to get these dependency changes automatically.

Streamlined implementation

Throughout this process, we went through several different “proofs of concept” to establish different ways users could implement design tokens.

We started small, testing subsets of tokens from their categories like:import {colorBlack} from @package-name/color

However, this proved to be tedious and we began to test other strategies that:

  • Made the import process less painful
  • Kept bundle-size down (through tree-shaking)
  • Reduce the amount of back and forth required

By collaborating with developers across our organization, we built up a list of requirements that helped inform what type of customizations our system needed to support.

Once we felt confident that we were able to generate accurate design tokens from extensible data, we began exploring how we could make further improvements to implementation and remove barriers through tooling.

PostCSS-themed

PostCSS-themed is an open source project we created to help support multiple themes, using CSS files.

An orange circle logo for PostCSS-themed

A user could set non-themeable values in a CSS file and then set their themeable values through theme.ts. This was technically working, but there was an issue with this approach: users would need to hop back and forth between these two files to define their design token usage.

We solved this problem by adding new functionality to our plugin: postcss-themed would now be able to support objects… which means we could implement component-specific design tokens directly in CSS! 🎉

Instead of developers having to:

  1. Assign variables in CSS
  2. Define those variables in a separate theme file
  3. Cross-reference tokens with what’s in the tokens Storybook…

Now we’ve unlocked the ability for developers to implement a design token that points directly to a component’s attribute in ONE CSS file:

font-weight: @theme link.linkTextDefaultFontWeight;

And because the data from our system supplies values for multiple themes, we no longer have to manually store those definitions in our component repos.

Custom VS Code extension

We wanted to meet developers where they were: in their IDE. The best way to accomplish this was through a custom VS Code extension.

Part of our acceptance criteria was to:

  • Allow users to auto-complete tokens based on what was available
  • Show a snippet of the token’s value
  • Bonus points: color previews
Our custom VSCode extension that shows a visual preview of design token values

Using this extension, developers can now quickly search through available tokens within VS Code and confirm the value that the token was pointing to, which meant we had improved:

  • Speed (autofill)
  • Confidence (token value)
  • QA (visual preview)

It’s sped up our implementation workflow significantly, since the design token and its context are in the same place. This also helps with troubleshooting, since we can quickly identify if a token is being used in the wrong slot.

While the extension is currently internal-facing only, we’d like to eventually make it open-source.

What’s next

Having a centralized design data source has amplified our design system by acting as a unifying thread that connects products, platforms, design, and code.

Our team is excited about contributing more design tokens tooling including:

  • Figma plugins to improve the designer/developer handshake process
  • Enhanced automated visual testing around token implementation
  • An adoption metrics dashboard

While there are still plenty of ways we can improve how our system works, I am thrilled at the progress we’ve made and the potential we’ve unlocked.

This project wouldn’t be the success that it is, if it weren’t for these wonderful folks: Adam Dierkens, Adil Malik, Andrew Lisowski, and Tyler Krupicka!

--

--