Designing Tokens — What makes great design tokens, and how to build them (Part 1)

What Are Design Tokens?

Design Tokens are essentially the tiniest pieces of reusable UI information that makes up your application. Think colors, fonts, and breakpoints.

const tokens = {
orange: "#ff9b00",
purple: "#5f259f",
blue: "#0096e6",
red: "#ff0000",
white: "#ffffff",
lightGray: "#b2b2b2",
gray: "#999999",
darkGray: "#333333",
};
const MyBanner = styled.div`
color: ${tokens.darkGray}; //color: #333333
background-color: ${tokens.purple};
`;

The Process

In this article, I will explain the problems and solutions that led to my final proposed way of consuming design tokens.

Iteration 1 — Grouping color by usage

The first problem with the basic implementation is that our token doesn’t tell us where the colors can be used. In most websites, there are certain rules around where a color can be used.

const MyBanner = styled.div`
color: ${tokens.text.darkGray}; //color: #333333
background-color: ${tokens.background.purple};
`;

Iteration 2 — Grouping tokens by type

Colors are not the only tokens. Chances are, your website also have defined other tokens like font sizes, line height, breakpoints, z-index etc.

const MyBanner = styled.div`
color: ${tokens.color.text.darkGray}; //color: #333333
background-color: ${tokens.color.background.purple};
font-size: ${tokens.size.font.sm1};
line-height: ${tokens.size.lineHeight.small};
@media (min-width: ${tokens.layout.media.tablet}) {
font-size: ${tokens.size.font.lg1};
z-index: ${tokens.layout.zIndex.bottomlessPit};
}
`;

Iteration 3 — Merging token key with token value

The next issue is that things are getting quite of long. We’ve also got a lot of repetition going on.background-color: tokens.color.background.purple for example, have “color” and “background” twice in the same line.

const {color, size, layout} = tokens;const MyBanner = styled.div`
${color.text.darkGray}; //color: #333333
${color.background.purple};
${size.font.sm1};
${size.lineHeight.small};
${layout.media.tablet} {
${size.font.lg1};
${layout.zIndex.bottomlessPit};
}
`;

Iteration 4 — Naming colors by function

With the simplified interface, our tokens are now much more readable, but there’s still room for improvements.

color: {   
text: {
brand1
brand2
default
alt
inverse
inverseAlt
interaction
interactionHover
interactionActive
disabled
error
success
},
background: {
brand1
brand2
interaction
...
},
border: {
brand1
brand2
interaction
...
}
}
const MyBanner = styled.div`
${color.text.alt}; //color: #999999 OR color: #FFC0CB
${color.background.main1};
${color.border.alt};
`;

Iteration 5 — Intellisense

Naming color tokens by their purpose solves the flexibility issue but it makes things slightly difficult for consumption. Consider, if you’ve been handed a design, at a glance, how do you know if a particular banner is using color.background.brand1 or color.background.brand2?

Iteration 6 — Expose token name as Typescript interface

We are almost there, there’s just one more thing to consider. Sometimes the style of a component is not coded into the component itself, but passed in as a prop. Consider, if you have a text component that accepts a color prop:

// Definition
const FontIcon = styled.span`
color: ${props => props.color}
...
`
// Usage
<FontIcon color="#333333"/>
<FontIcon color="#ff9b00"/>
<FontIcon color="#0096e6"/>
import { IconColorKeys } from '@tokens'// Definition
interface IconProp {
// "default" | "interaction" | "brand1"
color: IconColorKeys
}
const FontIcon = styled.span<IconProp>`
${props=>color.icon[props.color]}
...
`
//Usage
<FontIcon color="default" />
<FontIcon color="brand1" />
<FontIcon color="interaction"/>

Conclusion

After 6 iterations, this is our final token interface.

import { tokens, FontSizeKeys } from '@tokens'interface BannerProp {
fontSize: FontSizeKeys;
}
const {color, size, layout} = tokens;const Banner = styled.div<BannerProp>`
${color.bg.default};
${color.text.default};
${size.lineHeight.small};
${({fontSize: fontSizeName}) => size.font[fontSizeName]}
${layout.media.tablet} {
${layout.zIndex.bottomlessPit};
}
`
<Banner fontSize="small"/>

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
David Xu

David Xu

Code monkey specializing in React.js