style-dictionary-utils
is a collection of parsers
, filters
, transformers
and formats
for Style Dictionary that make working with w3c design tokens a lot easier.
Install the style-dictionary-utils
as well as style-dictionary
.
npm i -D style-dictionary-utils style-dictionary
If you are using .json5
files to define your design tokens install json5
as well.
npm i -D json5
The easiest way to use style-dictionary-utils
is to import the prepared StyleDictionary
object into your build file:
// build.ts
import StyleDictionary from 'style-dictionary-utils'
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['color/hexAlpha', 'shadow/css'],
"files": [{
"filter": "isSource",
"destination": "tokens.ts",
"format": "javascript/esm",
}]
}
}
});
myStyleDictionary.buildAllPlatforms();
Now all the included utilities* are available to you via the keys mentioned in the docs below.
* You only need to register the w3cTokenJson5Parser
if you want to use json5
.
You can still extend style dictionary with your own transformers and formats like before.
The only difference is that you must use the StyleDictionary
object that you import from style-dictionary-utils
.
// build.ts
import StyleDictionary from 'style-dictionary-utils'
StyleDictionary.registerTransform({
name: 'transform/pxToRem',
type: `value`,
transitive: true,
transformer: () => // ...
})
Look at the tests to get an idea how it works.
- Parsers
- Formats
- Transformers
- Filters
- Special Filter
This parser parses .json
with w3c design tokens.
This means the following files can be used with this parser.
{
"token": {
"value": "#223344",
"type": "color",
"description": "token description"
},
"w3cToken": {
"$value": "#223344",
"$type": "color",
"$description": "token description"
}
}
The parser will keep most propertys as is and only change $value
to value
and $description
or description
to comment
. This required for Style Dictionary.
To register the parsers add the following code to your build file.
import StyleDictionary from 'style-dictionary-utils'
import { w3cTokenJsonParser } from 'style-dictionary-utils/dist/parser/w3c-token-json-parser'
StyleDictionary.registerParser(w3cTokenJsonParser)
If you are using .json5
or .jsonc
files to define your design tokens you need to use the w3cTokenJson5Parser
. This is NOT enabled by default as it requires an additonal package, json5
, to work.
This parser is exactly the same as the w3cTokenJsonParser
with the only difference that it can parse .json5
or .jsonc
.
To register the parsers add the following code to your build file.
import StyleDictionary from 'style-dictionary-utils'
import { w3cTokenJson5Parser } from 'style-dictionary-utils/dist/parser/w3c-token-json5-parser'
StyleDictionary.registerParser(w3cTokenJson5Parser)
Make sure to install json5
by running npm i -D json5
.
If you’re using Prettier, be aware that the default configuration removes quote props, which are needed in $type
and $value
props in order to parse the tokens.
Here’s an example of a prettier config that overrides the default:
semi: false
singleQuote: true
overrides:
- files: '*.json[c|5]'
options:
quoteProps: preserve
singleQuote: false
The javascript/esm
format exports a token dictionary as an es6 export
statement.
export default {
colors: {
primary: '#0D70E6'
}
}
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
// ...
"format": "javascript/esm",
}]
}
}
});
The javascript/commonJs
format exports a token dictionary as an commonJs module
.
exports.default = {
colors: {
primary: '#0D70E6'
}
}
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"js": {
"transforms": //...,
"files": [{
// ...
"format": "javascript/commonJs",
}]
}
}
});
Transforms change the value
or name
of a token.
You can use transforms by refering the name in the array value of the transforms
property of a platform
.
If you want to use the same transformers
multiple times you can create a transform group
for easy reference.
StyleDictionary.registerTransformGroup({
name: 'webHex',
transforms: [
'color/hexAlpha',
'dimension/pixelToRem',
'font/css'
]
});
This packages ships a predefined transform group, called css/extended
.
It includes all transforms from the original css
transform group as well as the following transforms: color/rgbAlpha
, shadow/css
, font/css
, fontFamily/css
, fontWeight/number
, name/pathToDotNotation
, cubicBezier/css
, border/css
.
You can use it like any other transform Group:
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"css": {
"transformGroup": 'css/extended',
"files": [{
// ...
}]
}
}
});
This name
transformer replaces the token name with the entire path of the token in dot.notation.
This is especially useful for flat .js
or .json
files.
To use it simply add name/pathToDotNotation
to the transforms
array.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['name/pathToDotNotation'],
"files": [{
// ...
}]
}
}
});
{
colors: {
red: {
100: {
// ...
}
}
}
}
{
"colors.red.100": {
// ...
}
}
This value
transformer replaces the value of a token with a $type
or type
of color
with an rgba
string. If the token has an alpha
value, it will be used as the alpha
of the rgba
string.
Note: If your initial color value has an alpha value (e.g. hex8
) AND you add an alpha
property, the alpha
property will simply replace the previous alpha value.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['color/rgbAlpha'],
"files": [{
// ...
}]
}
}
});
{
colors: {
blue: {
500: {
value: "#0D70E6",
$type: "color",
alpha: 0.4
}
}
}
}
{
colors: {
blue: {
500: {
value: "rgba(13, 112, 230, 0.4)",
$type: "color",
alpha: 0.4
}
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of color
with a hex
string. If the token has an alpha
value, it will be used as the alpha
of the hex8
string.
Note: If your initial color value has an alpha value (e.g. rgba
) AND you add an alpha
property, the alpha
property will simply replace the previous alpha value.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['color/hexAlpha'],
"files": [{
// ...
}]
}
}
});
{
colors: {
blue: {
500: {
value: "rgba(13, 112, 230, 0.4)",
$type: "color",
alpha: 0.2
}
}
}
}
{
colors: {
blue: {
500: {
value: "#0D70E633", // prev alpha value is replaced with 0.2 from alpha property
$type: "color",
alpha: 0.2
}
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of color
with a hex
string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['color/hex'],
"files": [{
// ...
}]
}
}
});
{
colors: {
blue: {
500: {
value: "rgba(13, 112, 230, 0.4)",
$type: "color"
}
}
}
}
{
colors: {
blue: {
500: {
value: "#0D70E666",
$type: "color"
}
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of color
with an rgba
string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['color/rgba'],
"files": [{
// ...
}]
}
}
});
{
colors: {
blue: {
500: {
value: "#0D70E666",
$type: "color"
}
}
}
}
{
colors: {
blue: {
500: {
value: "rgba(13, 112, 230, 0.4)",
$type: "color"
}
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of color
with an rgba float
object.
This is helpful for tools and platforms and use float rgba values where the r
, g
, b
and a
values go from 0
to 1
. For example when preparing tokens to be imported into Figma.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"json": {
"transforms": ['color/rgbaFloat'],
"files": [{
// ...
}]
}
}
});
{
colors: {
blue: {
500: {
value: "#0D70E666",
$type: "color"
}
}
}
}
{
colors: {
blue: {
500: {
value: {
r: 0.051,
g: 0.439,
b: 0.902,
a: 0.4
},
$type: "color"
}
}
}
}
This value
transformer replaces the value of a w3c shadow token with a $type
or type
of shadow
with a css
shadow string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['shadow/css'],
"files": [{
// ...
}]
}
}
});
{
shadow: {
small: {
value: {
"color": "#00000066",
"offsetX": "0px",
"offsetY": "1px",
"blur": "2px",
"spread": "0px"
},
$type: "shadow"
}
}
}
{
shadow: {
small: {
value: "0px 1px 2px 0px #00000066",
$type: "shadow"
}
}
}
This value
transformer replaces the value of a w3c typography token with a $type
or type
of typography
with a css
font string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['font/css'],
"files": [{
// ...
}]
}
}
});
{
typography: {
body: {
value: {
fontWeight: 500,
fontSize: "16px",
lineHeight: "22px",
fontFamily: "Helvetica",
fontStyle: "italic"
},
$type: "typography"
}
}
}
{
typography: {
body: {
value: "italic 500 16px/22px Helvetica",
$type: "typography"
}
}
}
This value
transformer replaces the value of a w3c fontFamily token with a $type
or type
of fontFamily
with a css
fontFamily string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['fontFamily/css'],
"files": [{
// ...
}]
}
}
});
{
fontFamily: {
body: {
value: ['helvetica', 'sans-serif', 'Helvetica Neue'],
$type: "fontFamily"
}
}
}
{
fontFamily: {
body: {
value: "helvetica, sans-serif, 'Helvetica Neue'",
$type: "fontFamily"
}
}
}
This value
transformer replaces the value of a w3c fontWeight token with a $type
or type
of fontWeight
with a css
fontWeight number.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['fontWeight/number'],
"files": [{
// ...
}]
}
}
});
{
fontWeight: {
body: {
value: "light",
$type: "fontWeight"
}
}
}
{
fontWeight: {
body: {
value: 300,
$type: "fontWeight"
}
}
}
This value
transformer replaces the value of a w3c gradient token with a $type
or type
of gradient
with a css
gradient string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['gradient/css'],
"files": [{
// ...
}]
}
}
});
{
gradients: {
blueToGreen: {
angle: "45deg"
value: value: [
{
"color": "#288BD2",
"position": 0
},
{
"color": "#28D29F",
"position": 1
}
],
$type: "gradient"
}
}
}
{
gradients: {
blueToGreen: {
value: "45deg, #288BD2 0%, #28D29F 100%",
$type: "gradient"
}
}
}
This value
transformer replaces the value of a w3c cubicBezier token with a $type
or type
of cubicBezier
with a css
cubicBezier string.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['cubicBezier/css'],
"files": [{
// ...
}]
}
}
});
{
shadow: {
small: {
value: {
x1: 0.5,
y1: 0,
x2: 1,
y2: 1
},
$type: "cubicBezier"
}
}
}
{
shadow: {
small: {
value: "cubic-bezier(0.5, 0, 1, 1)",
$type: "cubicBezier"
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of dimension
that has a px
value, with a rem
value.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['dimension/pixelToRem'],
"files": [{
// ...
}],
options: {
basePxFontSize: 16
}
}
}
});
{
size: {
small: {
value: "32px",
$type: "dimension"
}
}
}
{
size: {
small: {
value: "2rem",
$type: "dimension"
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of dimension
that has a rem
value, with a px
value.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": ['dimension/remToPixel'],
"files": [{
// ...
}],
options: {
basePxFontSize: 16
}
}
}
});
{
size: {
small: {
value: "2rem",
$type: "dimension"
}
}
}
{
size: {
small: {
value: "32px",
$type: "dimension"
}
}
}
This value
transformer replaces the value of a token with a $type
or type
of dimension
that has a rem
or px
value, with a unitless pixel
based value. This is useful for example when preparing tokens to be imported into Figma.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"json": {
"transforms": ['dimension/pixelUnitless'],
"files": [{
// ...
}],
options: {
basePxFontSize: 16
}
}
}
});
This value
transformer replaces the value of a token with a $type
or type
of clamp
that has a $value
object with min
, ideal
and max
property, with a css clamp
function.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"json": {
"transforms": ['clamp/css'],
"files": [{
// ...
}],
}
}
});
{
size: {
small: {
value: {
min: "1.5rem",
ideal: "0.5vw + 0.75rem",
max: "2.5rem"
},
$type: "clamp"
}
}
}
{
size: {
small: {
value: "clamp(1.5rem, 0.5vw + 0.75rem, 2.5rem)",
$type: "clamp"
}
}
}
Filters are used to filter out unwanted tokens when configuring output files
Only allows tokens that come from a source
file to be included in the output. Tokens from an include
will be removed.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isSource",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of color
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isColor",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of gradient
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isGradient",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of color
or gradient
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isColorOrGradient",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of typography
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isTypography",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of typography
, fontWeight
or fontFamily
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isTypographic",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of transition
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isTransition",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of strokeStyle
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isStrokeStyle",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of shadow
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isShadow",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of fontWeight
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isFontWeight",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of fontFamily
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isFontFamily",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of duration
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isDuration",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of dimension
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isDimension",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of cubicBezier
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isCubicBezier",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of border
.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isBorder",
// ...
}]
}
}
});
Only allows tokens with a type
or $type
property of clamp
and an object as the $value
with a min
, ideal
and max
property.
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isClamp",
// ...
}]
}
}
});
The getHasAttribute
function returns a filter
function that filters by one or multiple properties.
You can provide one or multiple arguments that are used to check of the token has at least one of those properties.
{
color: {
red: {
$value: 'red',
deprecated: true // e.g. check that a deprecated attribute exists
}
}
}
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttribute} from 'style-dictionary-utils/dist/filter/getHasAttribute'
StyleDictionary.registerFilter({
name: 'shouldAvoid',
matcher: getHasAttribute('deprecated','removed')
})
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttribute} from 'style-dictionary-utils/dist/filter/getHasAttribute'
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"deprecatedJson": {
"transforms": //...,
"files": [{
"filter": getHasAttribute('deprecated','removed'), // allows only tokens with a `deprecated` or `removed propery, e.g. if you want` to create a json with tokens not to use.
// ...
}]
}
}
});
The getHasAttributeValue
function returns a filter
function that filters by one or multiple properties that have a specific value.
You can provide a string
or array
of string
s for the first argument, to define which properties should be checked.
Similarily you can provide one value or an array
of values for the second argument, to define which values to check against. Note: If you provide an array of values every property can have either of those values.
getHasAttributeValue(attributes: string[], values: any[])
{
color: {
red: {
$value: 'red',
deprecated: true // e.g. check that a deprecated value exists and is `true`
}
}
}
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttributeValue} from 'style-dictionary-utils/dist/filter/getHasAttributeValue'
StyleDictionary.registerFilter({
name: 'isDeprecated',
matcher: getHasAttributeValue('deprecated',true)
})
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttributeValue} from 'style-dictionary-utils/dist/filter/getHasAttributeValue'
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"deprecatedJson": {
"transforms": //...,
"files": [{
"filter": getHasAttributeValue('deprecated',true), // allows only tokens with a `deprecated` property that is true
// ...
}]
}
}
});
The getIsType
function returns a filter
function that filters by one or multiple types.
You can provide one or multiple arguments that are used as types
to filter against the type
or $type
property.
import StyleDictionary from 'style-dictionary-utils'
import {getIsType} from 'style-dictionary-utils/dist/filter/getIsType'
StyleDictionary.registerFilter({
name: 'isAnimation',
matcher: getIsType('duration','transition', 'cubicBezier')
})
import StyleDictionary from 'style-dictionary-utils'
import {getIsType} from 'style-dictionary-utils/dist/filter/getIsType'
const myStyleDictionary = StyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": getIsType('size','dimension'), // allows only tokens with type `size` or `dimension`
// ...
}]
}
}
});