Original blog post can be found on the zeroheight blog

When I joined zeroheight almost 4 years ago I was happy to see there was already a sense of “color tokens” in the codebase. However, there were a few issues; one being that there were two files that had slightly different colors defined and the other being that they didn’t line up with what the designers were using in Figma.

What was our starting point?

First off, we needed to get the codebase into a place where it was only using one set of color tokens. For the most part, this was a case of doing a find-and-replace for the values that lined up. Then, for the few rogue colors we moved them across to the file we wanted to keep, knowing eventually we could consolidate them all down.

Things stayed like that for a while, there were rarely complaints from developers now there was only one file. However, that file did keep bloating. Since the colors didn’t match those in Figma, more and more colors would be added and increased confusion was caused as to what should be used. Then, Figma released Variables

Introducing Variables

This felt like the perfect moment for the designs to refresh how they had their color styles organized and then we could make it align perfectly with the development side of things too. And at the same time, we were building out features to help other design system teams do the same.

The work of moving from Styles to Variables was done by designers behind the scenes. But they did talk me through how they were planning to break down the colors into different collections that would involve a base color group and more semantic layers on top. It all seemed to make sense theoretically, but it was very different from what we currently had set up, so it would need some extra thinking to put it into practice.

Making it work

Once the Variables had been imported into a zeroheight token set, I was able to see how this would be exported when it came to the Design Token Community Group (DTCG) format. And right out of the gate, this wasn’t the most usable format for us. We refer to colors in our Styled Components and want to be able to access them using dot notation (without lots of extra layers).

This is where I had to go outside of the features we offer in zeroheight and write my own transformer for the tokens. This took the format from:

"zh": {
   "color": {
      "addElementTile": {
        "background": {
          "default": {
            "$type": "color",
            "$value": "{zh.color.base.background.highlight.light}"
          },
          "hover": {
            "$type": "color",
            "$value": "{zh.color.base.background.highlight.strong}"
          }
        }
      }
   }
}

To:

"zh": {
   "color": {
      "addElementTile": {
        "background": {
          "default": "#f63e7c0d",
          "hover": "#f63e7c1a"
        }
      }
   }
}

The transformer also makes a TypeScript declaration file so that developers get auto-complete to find the token they’re looking for.

However, usually, all they need to do is go to the design file to see what is being used, and copy-paste:

Driving adoption

To get the developers to use the new tokens, they needed to be in the codebase. I could have just added the transformed files directly into our main codebase however, we are starting to have a few smaller projects popping up that might also need to use them. So, I went down the route of creating a small NPM package and publishing it privately on GitHub to make it reusable for all projects that might need color tokens.

Once I installed it into our main repository we were then back to having two ways to declare colors. This meant it was time to make a choice, do I replace the old colors with tokens behind the scenes or do I leave them be and force a more obvious use of the new tokens? In the end, I decided that hiding the new tokens behind the old color file wouldn’t help change old habits. So, I replaced a few colors as examples and then announced to the engineering team that they should always be using tokens and replace old color variables as they went.

This was also the first time we made use of JSDoc’s `@deprecated` tag.

/**
 * @deprecated Use `import { Tokens } from '@zeroheight/flapjack-tokens'` where possible
*/

Putting this at the top of the old color file means that people get a blue warning line when they use an old color value (or ignore one already in place).

Luckily for us, because we are a small team it’s very easy to get everyone to see a Slack message and know they will do their best to follow it going forward. This means the changeover can happen over time as new features are added and old ones are refactored.

It’s been a very stop-start journey over the past few years, but it’s great to have designers and developers using the same language when it comes to colors tokens. This is the first step in the long journey of getting our design system in sync between design and code.

How we got our color tokens in sync