21-Dec

CSS, JavaScript

Why I love Style Dictionary, and why you should too

Style Dictionary is one of the very best tools I've ever encountered. It's powerful, fun, and great for managing your design tokens!

6 min read

·

By Kristofer Selbekk

·

December 21, 2021

Throughout the years, I have worked with lots of companies, trying to structure their front end code into reusable bits and pieces. At some places we created component libraries, created and maintained by the community. Other places we set up cross-functional design system teams, with complete autonomy and huge impacts.

I love working with design systems - and particularly the work I do with designers. It lets me peek into a world I don't master myself, while still collaborating intensely to create a shared product we all can use.

What are design tokens?

In order to create this shared product, we need to have a shared vocabulary. And in many ways, that's what design tokens are about.

If you've ever heard about Atomic Design, you can think of design tokens as the quarks of your design system. You might have molecules (a search widget or cards) composed of atoms (buttons, input fields and boxes), but what are those atoms composed of?

All atoms in design have colors, font styles, spacing values, drop shadows and some kind of transitions applied when they change state. And it's those discreet values – the colors, font styles, spacing values etc – that we define as design tokens.

Jina Anne came up with the concept of design tokens while working on the Salesforce design system, which has revolutionized the entire world of design systems for both me and the rest of the industry. So if you see her, tell her I said thanks 🤗

To make it a bit more clear - here are some design tokens as CSS variables:

:root {
  --spacing-sm: 0.5rem;
  --spacing-md: 1rem;
  --spacing-lg: 1.5rem;
}

Here, we have a (small) spacing scale, which have discreet names we can share between designers and developers, making less things lost in translation.

What is Style Dictionary?

The first lesson of using design tokens, is that you'll end up with a lot of them. In order to encapsulate all possible values in your design, you shouldn't be surprised if you end up with a hundred or more!

Structuring these tokens in a way that still makes them discoverable then becomes important. And what happens when your app team needs to use the same design tokens as you do in your scss-based front end?

Style Dictionary is a simple, yet very powerful, system for managing your design tokens. it lets you structure your tokens in whatever fashion makes sense to you (it ships with some neat defaults too, if you just want that structure decided for you), and it lets you export a normalized set of tokens into lots of different formats. Lastly, it's easily extendible to solve the needs that aren't solved by default.

Setting up your first tokens

To get started, create a new folder my-tokens and run npm init -y:

$ mkdir my-tokens
$ cd my-tokens
$ npm init -y

Next, let's install style-dictionary as a dev dependency:

$ npm install --save-dev style-dictionary

Now we're ready to add some tokens!

Tokens are saved as basic JSON-files (or plain JavaScript files if you want), placed in the tokens folder. You can structure your tokens as you'd like, but Style Dictionary suggests that you follow the CTI structure, which stands for Category, Type, Item.

Let's show you an example. If we want to add the spacing scale from our example, we would want the following structure:

❯ tree
.
└── tokens
    └── size
        └── spacing.json

Inside the spacing.json file, we would put the following code:

{
  "size": {
    "spacing": {
      "sm": {
        "value": 0.5
      },
      "md": {
        "value": 1
      },
      "lg": {
        "value": 1.5
      }
    }
  }
}

That looks like a lot of boilerplate instead of just creating an object with three key values in it, but luckily it's much more flexible than a plain old object would be! We'll look at how later.

In real life, you'll have much more tokens to deal with. You'll have size/font.json, size/borderRadius.json and a lot more. Style Dictionary will then merge all of these objects together, before processing them.

Configuring Style Dictionary

Next up, we need to specify how we want Style Dictionary wants to work for us. In our example, we want to consume tokens as SCSS variables, and JavaScript variables.

First, let's create the config file itself - config.json. Here's

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {},
    "javascript": {}
  }
}

This tells us that we want to base our transformations on all files that match the glob "tokens/**/*.json", which is all json-files inside any subfolder of the tokens folder. We also specify two different platforms we want to support.

Next, let's specify what we want to happen for the "scss" platform:

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "files": [{ 
        "format": "scss/variables", 
        "destination": "lib/_tokens.scss"
      }]
    },
    "javascript": {}
  }
}

Here, we specify that we want the "transform group" scss to be applied. A transform group is a – well, predefined group of transforms – that either ships with Style Dictionary, or that you specify programmatically. You can see all the predefined transform groups here, but the scss transform group includes the following transforms:

[
  "attribute/cti",
  "name/cti/kebab",
  "time/seconds",
  "content/icon",
  "size/rem",
  "color/css"
]

If you wanted to, you could specify this list instead of "transformGroup

We won't go into detail in what each of these transforms do, but we can kind of figure out that any timing related tokens will be assumed to be in seconds (and suffixed accordingly), and any sizes will be assumed to be rem-based. You can look at all the implementations of these transforms here.

After we've specified the transforms we want, we specify what files we want to generate, and what "format" we want that file to be in. For the SCSS case, we want to use the format "scss/variables", and we want to output the file to lib/_tokens.scss.

The "format" is a function that receives the combined JSON from the tokens folder, after being passed through all the transforms specified above, and returns a single string to be printed to file.

Next, let's add support for JavaScript tokens (and their corresponding TypeScript typings) as well:

{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "files": [{ 
        "format": "scss/variables", 
        "destination": "lib/_tokens.scss"
      }]
    },
    "javascript": {
      "transformGroup": "js",
      "files": [
        { 
          "format": "javascript/es6", 
          "destination": "lib/tokens.js"
        },
        { 
          "format": "typescript/es6-declarations", 
          "destination": "lib/tokens.d.ts"
        }
      ]
    }
  }
}

Here, we specify the transform group "js" (here's how that looks), and then we specify two different file outputs, with two different formats. One creating an ES6 export, and one creating the TypeScript declarations.

Creating the tokens

Alright, it's been a long way here, but we're ready. Let's create a new npm command to build our tokens!

{
  "scripts": {
    "build": "style-dictionary build"
  }
}

After we run npm run build, we should have three new files in our lib folder:

// lib/_tokens.scss
$size-spacing-sm: 0.5rem;
$size-spacing-md: 1rem;
$size-spacing-lg: 1.5rem;
// lib/tokens.js
export const SizeSpacingSm = "0.5rem";
export const SizeSpacingMd = "1rem";
export const SizeSpacingLg = "1.5rem";
// lib/tokens.d.ts
export const SizeSpacingSm : string;
export const SizeSpacingMd : string;
export const SizeSpacingLg : string;

The next step is to release the lib folder as an NPM package, and consume them in your various projects.

If you want to add support for ios or android tokens, for example, adding it is as simple as adding a few lines of configuration.

In summary

If you're using a design system, you should definitely be using design tokens. And if you're using design tokens, your life will be much easier if you use Style Dictionary to manage them. It's extensible, customizable, and well documented.

These are all reasons why I love Style Dictionary, and why you should too.