Utilities to use in your style dictionary config
npm install style-dictionary-utils

style-dictionary-utils is a collection of 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.
``bash`
npm i -D style-dictionary-utils style-dictionary
If you are not ready to upgrade to style dictinary version 3 you can continue using style-dictionary-utils by locking to v2 currently v2.4.1 version.
The easiest way to use style-dictionary-utils is to import the prepared StyleDictionary object into your build file:
`js
// build.ts
import {StyleDictionary} from 'style-dictionary-utils'
const myStyleDictionary = new StyleDictionary()
// when using style dictionary 4 you whave to await the extend method
const extendedSd = await myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['color/css', 'shadow/css'],
files: [
{
filter: 'isSource',
destination: 'tokens.ts',
format: 'javascript/esm',
},
],
},
},
})
extendedSd.buildAllPlatforms()
`
Now all the included utilities\* are available to you via the keys mentioned in the docs below.
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.
`js
// build.ts
import { StyleDictionary } from 'style-dictionary-utils'
StyleDictionary.registerTransform({
name: 'transform/pxToRem',
$type: value,`
transitive: true,
transform: () => // ...
})
Look at the tests to get an idea how it works.
- Formats
- css/advanced
- javascript/esm
- typescript/esm-declarations
- javascript/commonJs
- Transformers
- name/pathToDotNotation
- name/pathToCamelCase
- name/pathToPascalCase
- color/css
- typography/css
- fontFamily/css
- fontWeight/number
- gradient/css
- cubicBezier/css
- dimension/css
- clamp/css
- shadow/css
- number
- Filters
- isSource
- isColor
- isGradient
- isTypography
- isTransition
- isStrokeStyle
- isShadow
- isFontWeight
- isFontFamily
- isDuration
- isDimension
- isCubicBezier
- isBorder
- isClamp
- isNumber
- Special Filter
- getHasAttribute
- getHasAttributeValue
- getIsType
The css/advanced format exports a token dictionary as a css file with css variables. It allows you to define media queries that can wrap specific parts of your css variables. If nothing is defined the entire file will be wrapped in a :root selector.
You can change the selector by defining it in file.options.selector.
You can define rules on a file level using file.options.rules. If one or more rules are defined, only tokens within any of the rules will be output. You can define as many rule objects within file.options.rules as you want. Tokens can be part of one or multiple rules.
A rule object may have any or all of the three properties atRule, selector and matcher.
- selector is a string that is wrapped around your css. If the selector is undefined, the default selector or one define at file.options.selector will be used. If you don't want a selector, set it to false.atRule
- can be a string or array of strings, that are wrapped around the css and selector with the first being the outer layer.matcher
- is a filter function that returns true for tokens that should be included in the query. If you want to match all tokens, just return true from the matcher.
`css`
body[theme='dark'] {
--color-background-primary: #ff0000;
--color-background-secondary: #0000ff;
}
@media (min-width: 768px) {
body[theme='dark'] {
--color-button-primary: #c1c1c1;
--color-button-secondary: #007d79;
}
}
##### Usage
`jsbody[theme="dark"]
myStyleDictionary.extend({
"platforms": {
"css": {
"transforms": //...,
"files": [{
// ...
"format": "css/advanced",
"options": {
selector: , // defaults to :root; set to false to disablebody[size="medium"]
rules: [
{
atRule: '@media (min-width: 768px)',
selector: // this will be used instead of body[theme="dark"]
matcher: (token: StyleDictionary.TransformedToken) => token.filePath.includes('tablet'), // tokens that match this filter will be added inside the media query
}]
}
}]
}
}
});
``
The javascript/esm format exports a token dictionary as an es6 export statement.
`js`
export default {
colors: {
primary: '#0D70E6',
},
}
##### Usage
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
// ...
"format": "javascript/esm",
}]
}
}
});
The typescript/esm-declarations format exports a token dictionary as a typescript declaration file.
`js`
export default {
colors: {
primary: string,
},
}
##### Usage
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
// ...
"format": "typescript/esm-declarations",
}]
}
}
});
The javascript/commonJs format exports a token dictionary as an commonJs module.
`js`
exports.default = {
colors: {
primary: '#0D70E6',
},
}
##### Usage
`js`
myStyleDictionary.extend({
"platforms": {
"js": {
"transforms": //...,
"files": [{
// ...
"format": "javascript/commonJs",
}]
}
}
});
Transforms change the value or name of a token.transforms
You can use transforms by refering the name in the array value of the property of a platform.
If you want to use the same transformers multiple times you can create a transform group for easy reference.
`js`
myStyleDictionary.registerTransformGroup({
name: 'webHex',
transforms: ['color/css', 'dimension/css', 'typography/css'],
})
#### css/extended transform group
This packages ships a predefined transform group, called css/extended.css
It includes all transforms from the original transform group as well as the following transforms: color/css, shadow/css, typography/css, fontFamily/css, fontWeight/number, name/pathToDotNotation, cubicBezier/css, border/css.
You can use it like any other transform Group:
`js`
myStyleDictionary.extend({
platforms: {
css: {
transformGroup: 'css/extended',
files: [
{
// ...
},
],
},
},
})
This value transformer converts a w3c color token with a $type of color to a CSS color value. By default, it outputs colors in hex format, but you can control the output format using the colorOutputFormat platform option.
Supported output formats: hex, rgb, rgba, hsl, hsla, rgbFloat
`js`
myStyleDictionary.extend({
platforms: {
css: {
transforms: ['color/css'],
colorOutputFormat: 'hsl', // optional: defaults to 'hex'
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
color: {
primary: {
value: {
colorSpace: "srgb",
components: [0.051, 0.439, 0.902],
alpha: 1
},
$type: "color"
}
}
}
##### After transformation (hex format)
`js`
{
color: {
primary: {
value: "#0d70e6",
$type: "color"
}
}
}
This value transformer converts a w3c shadow token with a $type of shadow to a CSS shadow value. It supports both single shadows and multiple shadows (box-shadow).
`js`
myStyleDictionary.extend({
platforms: {
css: {
transforms: ['shadow/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
shadow: {
card: {
value: {
offsetX: {value: 0, unit: "px"},
offsetY: {value: 4, unit: "px"},
blur: {value: 8, unit: "px"},
spread: {value: 0, unit: "px"},
color: {
colorSpace: "srgb",
components: [0, 0, 0],
alpha: 0.1
}
},
$type: "shadow"
}
}
}
##### After transformation
`js`
{
shadow: {
card: {
value: "0px 4px 8px 0px #0000001a",
$type: "shadow"
}
}
}
This value transformer converts a w3c dimension token with a $type of dimension to a CSS dimension value. It can convert between px and rem units based on platform options.
Platform options:
- outputUnit: Target unit (px or rem, defaults to token's original unit)basePxFontSize
- : Base font size for px/rem conversion (defaults to 16)appendUnit
- : Whether to append the unit to the output (defaults to true)
`js`
myStyleDictionary.extend({
platforms: {
css: {
transforms: ['dimension/css'],
basePxFontSize: 16, // optional: base font size for rem conversion
outputUnit: 'rem', // optional: 'px' or 'rem'
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
spacing: {
medium: {
value: {
value: 16,
unit: "px"
},
$type: "dimension"
}
}
}
##### After transformation (with outputUnit: 'rem')
`js`
{
spacing: {
medium: {
value: "1rem",
$type: "dimension"
}
}
}
This name transformer replaces the token name with the entire path of the token in dot.notation..js
This is especially useful for flat or .json files.
To use it simply add name/pathToDotNotation to the transforms array.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['name/pathToDotNotation'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
colors: {
red: {
100: {
// ...
}
}
}
}
##### After transformation
`js`
{
"colors.red.100": {
// ...
}
}
This name transformer replaces the token name with the entire path of the token in camelCase notation.
To use it simply add name/pathToCamelCase to the transforms array.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['name/pathToCamelCase'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
colors: {
bg: {
default: {
// ...
}
}
}
}
##### After transformation
`js`
{
"colorsBgDefault": {
// ...
}
}
This name transformer replaces the token name with the entire path of the token in camelCase notation.
To use it simply add name/pathToPascalCase to the transforms array.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['name/pathToPascalCase'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
colors: {
bg: {
default: {
// ...
}
}
}
}
##### After transformation
`js`
{
"ColorsBgDefault": {
// ...
}
}
This value transformer replaces the value of a w3c typography token with a $type of typography with a css font string.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['typography/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
typography: {
body: {
value: {
fontWeight: 500,
fontSize: "16px",
lineHeight: "22px",
fontFamily: "Helvetica",
fontStyle: "italic"
},
$type: "typography"
}
}
}
##### After transformation
`js`
{
typography: {
body: {
value: "italic 500 16px/22px Helvetica",
$type: "typography"
}
}
}
This value transformer replaces the value of a w3c fontFamily token with a $type of fontFamily with a css fontFamily string.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['fontFamily/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
fontFamily: {
body: {
value: ['helvetica', 'sans-serif', 'Helvetica Neue'],
$type: "fontFamily"
}
}
}
##### After transformation
`js`
{
fontFamily: {
body: {
value: "helvetica, sans-serif, 'Helvetica Neue'",
$type: "fontFamily"
}
}
}
This value transformer replaces the value of a w3c fontWeight token with a $type of fontWeight with a css fontWeight number.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['fontWeight/number'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
fontWeight: {
body: {
value: "light",
$type: "fontWeight"
}
}
}
##### After transformation
`js`
{
fontWeight: {
body: {
value: 300,
$type: "fontWeight"
}
}
}
This value transformer replaces the value of a w3c gradient token with a $type of gradient with a css gradient string.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['gradient/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
gradients: {
blueToGreen: {
angle: "45deg"
value: value: [
{
"color": "#288BD2",
"position": 0
},
{
"color": "#28D29F",
"position": 1
}
],
$type: "gradient"
}
}
}
##### After transformation
`js`
{
gradients: {
blueToGreen: {
value: "45deg, #288BD2 0%, #28D29F 100%",
$type: "gradient"
}
}
}
This value transformer replaces the value of a w3c cubicBezier token with a $type of cubicBezier with a css cubicBezier string.
`js`
myStyleDictionary.extend({
platforms: {
ts: {
transforms: ['cubicBezier/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
shadow: {
small: {
value: {
x1: 0.5,
y1: 0,
x2: 1,
y2: 1
},
$type: "cubicBezier"
}
}
}
##### After transformation
`js`
{
shadow: {
small: {
value: "cubic-bezier(0.5, 0, 1, 1)",
$type: "cubicBezier"
}
}
}
This value transformer replaces the value of a token with a $type of clamp that has a $value object with min, ideal and max property, with a css clamp function.
`js`
myStyleDictionary.extend({
platforms: {
json: {
transforms: ['clamp/css'],
files: [
{
// ...
},
],
},
},
})
##### Before transformation
`js`
{
size: {
small: {
value: {
min: "1.5rem",
ideal: "0.5vw + 0.75rem",
max: "2.5rem"
},
$type: "clamp"
}
}
}
##### After transformation
`js`
{
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
Each filter is available in two ways:
1. As a registered filter - Use the filter name as a string (e.g., "isSource") in your Style Dictionary configurationisSourceFilter
2. As an importable function - Import the filter function directly (e.g., ) for use in custom transformers or advanced filtering
`js
// Using registered filter by name
myStyleDictionary.extend({
platforms: {
ts: {
files: [{
filter: "isSource", // ← registered filter name
// ...
}]
}
}
});
// Importing and using filter function directly
import {isSourceFilter} from 'style-dictionary-utils/filter/isSource.js'
// Use in custom transformer
StyleDictionary.registerTransform({
name: 'my-custom-transform',
filter: isSourceFilter, // ← imported filter function
transform: (token) => // ...
});
`
Only allows tokens that come from a source file to be included in the output. Tokens from an include will be removed.
Filter name: "isSource" isSourceFilter
Import function: from 'style-dictionary-utils/filter/isSource.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isSource",
// ...
}]
}
}
});
Only allows tokens with a $type property of color.
Filter name: "isColor" isColorFilter
Import function: from 'style-dictionary-utils/filter/isColor.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isColor",
// ...
}]
}
}
});
Only allows tokens with a $type property of gradient.
Filter name: "isGradient" isGradientFilter
Import function: from 'style-dictionary-utils/filter/isGradient.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isGradient",
// ...
}]
}
}
});
Only allows tokens with a $type property of typography.
Filter name: "isTypography" isTypographyFilter
Import function: from 'style-dictionary-utils/filter/isTypography.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isTypography",
// ...
}]
}
}
});
Only allows tokens with a $type property of transition.
Filter name: "isTransition" isTransitionFilter
Import function: from 'style-dictionary-utils/filter/isTransition.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isTransition",
// ...
}]
}
}
});
Only allows tokens with a $type property of strokeStyle.
Filter name: "isStrokeStyle" isStrokeStyleFilter
Import function: from 'style-dictionary-utils/filter/isStrokeStyle.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isStrokeStyle",
// ...
}]
}
}
});
Only allows tokens with a $type property of shadow.
Filter name: "isShadow" isShadowFilter
Import function: from 'style-dictionary-utils/filter/isShadow.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isShadow",
// ...
}]
}
}
});
Only allows tokens with a $type property of fontWeight.
Filter name: "isFontWeight" isFontWeightFilter
Import function: from 'style-dictionary-utils/filter/isFontWeight.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isFontWeight",
// ...
}]
}
}
});
Only allows tokens with a $type property of fontFamily.
Filter name: "isFontFamily" isFontFamilyFilter
Import function: from 'style-dictionary-utils/filter/isFontFamily.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isFontFamily",
// ...
}]
}
}
});
Only allows tokens with a $type property of duration.
Filter name: "isDuration" isDurationFilter
Import function: from 'style-dictionary-utils/filter/isDuration.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isDuration",
// ...
}]
}
}
});
Only allows tokens with a $type property of dimension.
Filter name: "isDimension" isDimensionFilter
Import function: from 'style-dictionary-utils/filter/isDimension.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isDimension",
// ...
}]
}
}
});
Only allows tokens with a $type property of cubicBezier.
Filter name: "isCubicBezier" isCubicBezierFilter
Import function: from 'style-dictionary-utils/filter/isCubicBezier.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isCubicBezier",
// ...
}]
}
}
});
Only allows tokens with a $type property of border.
Filter name: "isBorder" isBorderFilter
Import function: from 'style-dictionary-utils/filter/isBorder.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isBorder",
// ...
}]
}
}
});
Only allows tokens with a $type property of clamp and an object as the $value with a min, ideal and max property.
Filter name: "isClamp" isClampFilter
Import function: from 'style-dictionary-utils/filter/isClamp.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isClamp",
// ...
}]
}
}
});
Only allows tokens with a $type property of number.
Filter name: "isNumber" isNumberFilter
Import function: from 'style-dictionary-utils/filter/isNumber.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isNumber",
// ...
}]
}
}
});
Only allows tokens with a $deprecated property that is either true or a string (deprecation message).
Filter name: "isDeprecated" isDeprecatedFilter
Import function: from 'style-dictionary-utils/filter/isDeprecated.js'
`js`
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": "isDeprecated",
// ...
}]
}
}
});
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.
`js`
{
color: {
red: {
$value: 'red',
deprecated: true // e.g. check that a deprecated attribute exists
}
}
}
##### Register as a new filter
`js
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttribute} from 'style-dictionary-utils/filter/getHasAttribute.js'
StyleDictionary.registerFilter({
name: 'shouldAvoid',
matcher: getHasAttribute('deprecated', 'removed'),
})
`
##### Use directly in platform
`js
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttribute} from 'style-dictionary-utils/filter/getHasAttribute.js'
myStyleDictionary.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.string
You can provide a or array of strings for the first argument, to define which properties should be checked.array
Similarily you can provide one value or an 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.
`js`
getHasAttributeValue(attributes: string[], values: any[])
`jstrue
{
color: {
red: {
$value: 'red',
deprecated: true // e.g. check that a deprecated value exists and is `
}
}
}
##### Register as a new filter
`js
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttributeValue} from 'style-dictionary-utils/filter/getHasAttributeValue.js'
StyleDictionary.registerFilter({
name: 'isDeprecated',
matcher: getHasAttributeValue('deprecated', true),
})
`
##### Use directly in platform
`js
import StyleDictionary from 'style-dictionary-utils'
import {getHasAttributeValue} from 'style-dictionary-utils/filter/getHasAttributeValue.js'
myStyleDictionary.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.$type
You can provide one or multiple arguments that are used as types to filter against the property.
##### Register as a new filter
`js
import StyleDictionary from 'style-dictionary-utils'
import {getIsType} from 'style-dictionary-utils/filter/getIsType.js'
StyleDictionary.registerFilter({
name: 'isAnimation',
matcher: getIsType('duration', 'transition', 'cubicBezier'),
})
`
##### Use directly in platform
`js
import StyleDictionary from 'style-dictionary-utils'
import {getIsType} from 'style-dictionary-utils/filter/getIsType.js'
myStyleDictionary.extend({
"platforms": {
"ts": {
"transforms": //...,
"files": [{
"filter": getIsType('size','dimension'), // allows only tokens with $type size or dimension``
// ...
}]
}
}
});