I'm often asked: "What's the difference between Specify and Style Dictionary?". My answer is always the same: "Yes, they look alike, and Specify is not meant to replace Style Dictionary: it actually enhances it.".
Let's see why together.
This article helps you understand:
- differences between Specify and Style Dictionary
- how to couple them to generate design tokens and assets
Style Dictionary and Specify are both design tokens generators, and you can use them to generate design tokens and assets respecting your company standards.
What is Style Dictionary?
Created by Danny Banks in 2017, Style Dictionary is a build system that allows you to generate styles for any platform from static design tokens in an agnostic format (e.g., JSON).
For instance, you can feed Style Dictionary with raw colors in JSON and configure it to generate colors in specific formats for different platforms like Android (e.g., Kotlin), iOS (e.g., Swift), or Web (e.g., Sass).
Style Dictionary is open source and available through a CLI or a node module.
Style Dictionary generates design data
Style Dictionary provides out-of-the-box transforms functions to help you create and transform design tokens. Transforms are functions that range from converting colors to HSL
, converting dimension design tokens from rem
to dp
, or even converting an image in base64
.
In short, Style Dictionary helps you transform your design tokens to make them compatible with your company standards.
But Style Dictionary doesn't sync your design data
Keeping design data up-to-date at scale means transforming your design tokens for target platforms every time a design token is updated.
Style Dictionary helps with the transformation part, but you still need to run it every time your design tokens get updated.
See for yourself
First of all, let's install Style Dictionary in our directory: yarn add style-dictionary
.
Now, let's generate our design tokens, shall we!
yarn run style-dictionary init basic
This command generates:
- A
tokens
folder containing agnostic colors and sizes - A Style Dictionary configuration file:
config.json
- Our design tokens in Swift, Objective C, XML, Kotlin and SCSS in a
build
folder - A
README.md
file describing us what this configuration is doing
Want to know more about this command?
Check out the official examples projects provided by Style Dictionary. In our case, we just used the basic
example π
Style Dictionary helps you generate and transform your design tokens. But you still need to run Style Dictionary every time they get updated.
Why Specify and Style Dictionary make the perfect match
Specify is a Design API that helps you collect design data from Figma and distribute it in the right format, in the right project, at the right time, and to top it all: automatically.
Let's focus on the "distribution" part. Like Style Dictionary, Specify helps you generate design data for any target platforms.
By default Specify returns design data in JSON but thanks its open source parsers you can transform your design data in any formats. I repeat, in any formats.
Are you starting to see where I'm going here?
Specify can generate design tokens compatible with Style Dictionary. The same ones you feed Style Dictionary with. And as good things come in pairs, Specify automatically detects updates coming Figma and updates agnostic design tokens consumed by Style Dictionary.
Working example
This example project will help you understand how to use Specify and Style Dictionary together.
Please make sure you already have synchronized design tokens in a Specify repository. Want to learn more about this? Watch this 3min tutorial π¬
From there, we will:
- Pull design data from Specify and generate agnostic design tokens compatible with Style Dictionary
- Run Style Dictionary and generate design tokens for iOS, Android, and Web
Specify and Style Dictionary are both flexible and powerful generators. However, we must configure them so they understand what to generate for us.
From Specify to Style Dictionary
Let's start by pulling our design data from Specify in our project. The "project" I'm referring to is a directory called your-project
.
We will use the Specify CLI to pull design data programmatically from a local directory.
Let's install it by running in the terminal: yarn add @specify/cli
.
If things went well you should have the following help menu displayed after running the following command: specify
.
Instead of manually configuring Specify, we will ask Specify to generate a working configuration designed for Style Dictionary.
Under the hood, this configuration is mostly using the to-style-dictionary parser.
Here's a short video showing how Specify can generate design tokens compatible with Style Dictionary:
Let's break down what we just did here:
- We created a Specify configuration file tailored for Style Dictionary with the command
specify init
- We finalized the configuration by updating the Specify repository and our
personalAccessToken
- We pulled our design tokens and assets with the command
specify pull
.
Which generated the following files:
π output
βββ π tokens
| βββ π color
| | βββ base.json
| βββ π asset
| βββ font.json
| βββ icon.json
βββ π assets
βββ π fonts
βββ π vectors
What now? Now we've generated agnostic colors, icons and font files, it's time to transform them with Style Dictionary.
From Style Dictionary to target platforms
Here's the following workflow we want to setup:
Now we have agnostic design tokens at hand let's configure Style Dictionary to transform them.
Remove example tokens and use the ones coming from Specify
Instead of writing our configuration from scratch we'll update the one Style Dictionary generated for us with the init
command. We want Style Dictionary to run our config against tokens located in the output/
folder Specify generated.
Update the Style Dictionary config file
Our config.json
file becomes:
{
"source": ["output/**/*.json"],
"platforms": {
"scss": {
"transformGroup": "scss",
"buildPath": "build/scss/",
"files": [{
"destination": "_variables.scss",
"format": "scss/variables"
}]
},
"android": {
"transformGroup": "android",
"buildPath": "build/android/",
"files": [{
"destination": "font_dimens.xml",
"format": "android/fontDimens"
},{
"destination": "colors.xml",
"format": "android/colors"
}]
},
"compose": {
"transformGroup": "compose",
"buildPath": "build/compose/",
"files": [{
"destination": "StyleDictionaryColor.kt",
"format": "compose/object",
"className": "StyleDictionaryColor",
"packageName": "StyleDictionaryColor",
"filter": {
"attributes": {
"category": "color"
}
}
},{
"destination": "StyleDictionarySize.kt",
"format": "compose/object",
"className": "StyleDictionarySize",
"packageName": "StyleDictionarySize",
"type": "float",
"filter": {
"attributes": {
"category": "size"
}
}
}]
},
"ios": {
"transformGroup": "ios",
"buildPath": "build/ios/",
"files": [{
"destination": "StyleDictionaryColor.h",
"format": "ios/colors.h",
"className": "StyleDictionaryColor",
"type": "StyleDictionaryColorName",
"filter": {
"attributes": {
"category": "color"
}
}
},{
"destination": "StyleDictionaryColor.m",
"format": "ios/colors.m",
"className": "StyleDictionaryColor",
"type": "StyleDictionaryColorName",
"filter": {
"attributes": {
"category": "color"
}
}
},{
"destination": "StyleDictionarySize.h",
"format": "ios/static.h",
"className": "StyleDictionarySize",
"type": "float",
"filter": {
"attributes": {
"category": "size"
}
}
},{
"destination": "StyleDictionarySize.m",
"format": "ios/static.m",
"className": "StyleDictionarySize",
"type": "float",
"filter": {
"attributes": {
"category": "size"
}
}
}]
},
"ios-swift": {
"transformGroup": "ios-swift",
"buildPath": "build/ios-swift/",
"files": [{
"destination": "StyleDictionary+Class.swift",
"format": "ios-swift/class.swift",
"className": "StyleDictionaryClass",
"filter": {}
},{
"destination": "StyleDictionary+Enum.swift",
"format": "ios-swift/enum.swift",
"className": "StyleDictionaryEnum",
"filter": {}
},{
"destination": "StyleDictionary+Struct.swift",
"format": "ios-swift/any.swift",
"className": "StyleDictionaryStruct",
"filter": {},
"options": {
"imports": "SwiftUI",
"objectType": "struct",
"accessControl": "internal"
}
}]
},
"ios-swift-separate-enums": {
"transformGroup": "ios-swift-separate",
"buildPath": "build/ios-swift/",
"files": [{
"destination": "StyleDictionaryColor.swift",
"format": "ios-swift/enum.swift",
"className": "StyleDictionaryColor",
"filter": {
"attributes": {
"category": "color"
}
}
},{
"destination": "StyleDictionarySize.swift",
"format": "ios-swift/enum.swift",
"className": "StyleDictionarySize",
"filter": {
"attributes": {
"category": "size"
}
}
}]
}
}
}
Generate tokens for target platforms-
Now if we run yarn run style-dictionary build
we see our colors, vectors and font files transformed for our target platforms.
Did you see the magic happen here?
The config.json
is composed of two main properties:
- The
source
property tells Style Dictionary where to look for design tokens (in our case theoutput
folder) - The
platforms
property tells Style Dictionary how to transform our design tokens
Let's sum things up
We just saw how Specify generates design tokens for Style Dictionary while keeping them up-to-date.
Specify helps you generate design tokens that are always updated so you can transform them with Style Dictionary. Specify doesn't replace Style Dictionary. It enhances it.
In our working example we used the Specify CLI and executed Style Dictionary in a local directory. However, you could totally set this workflow in a GitHub repository thanks to a GitHub Action. But this is for another blog post.
Cheers βοΈ