Skip to content

Example

This example converts tokens into CSS with @property format, using regular CSS custom properties with light-dark() for color-scheme and constraind tokens for density.

Input

json
{
  "sizing": {
    "base": {
      "$value": "1em",
      "$description": "",
      "$type": "dimension"
    },
    "ratio": {
      "$value": 1.3,
      "$description": "",
      "$type": "number"
    }
  }
}
json
{
  "palette": {
    "brand": {
      "red": {
        "$value": "#e41b1b",
        "$description": "",
        "$type": "color"
      },
      "400": {
        "$value": {
          "value": "{palette.brand.500}",
          "transforms": {
            "lightness": -10
          }
        },
        "$description": "",
        "$type": "color"
      },
      "500": {
        "$value": "{palette.brand.red}",
        "$description": "",
        "$type": "color"
      },
      "600": {
        "$value": {
          "value": "{palette.brand.500}",
          "transforms": {
            "lightness": 10
          }
        },
        "$description": "",
        "$type": "color"
      }
    }
  }
}
json
{
  "layout": {
    "background": {
      "$value": [
        {
          "value": "{palette.structure.white}",
          "features": {
            "color-scheme": "light"
          }
        },
        {
          "value": "{palette.structure.200}",
          "features": {
            "color-scheme": "dark"
          }
        }
      ],
      "$description": "",
      "$type": "color"
    },
    "contrast": {
      "$value": [
        {
          "value": "{palette.structure.900}",
          "features": {
            "color-scheme": "light"
          }
        },
        {
          "value": "{palette.structure.400}",
          "features": {
            "color-scheme": "dark"
          }
        }
      ],
      "$description": "",
      "$type": "color"
    }
  }
}
json
{
  "intent": {
    "action": {
      "base": {
        "background": {
          "$value": "{palette.brand.500}",
          "$description": "",
          "$type": "color"
        },
        "border": {
          "$value": "{intent.action.base.background}",
          "$description": "",
          "$type": "color"
        },
        "text": {
          "$value": "{palette.letters.brand-highlight}",
          "$description": "",
          "$type": "color"
        }
      },
      "disabled": {
        "background": {
          "$value": {
            "value": "{intent.action.base.background}",
            "transforms": {
              "alpha": -35
            }
          },
          "$description": "",
          "$type": "color"
        },
        "border": {
          "$value": {
            "value": "{intent.action.base.border}",
            "transforms": {
              "alpha": -35
            }
          },
          "$description": "",
          "$type": "color"
        },
        "text": {
          "$value": {
            "value": "{intent.action.base.text}",
            "transforms": {
              "alpha": -35
            }
          },
          "$description": "",
          "$type": "color"
        }
      }
    }
  }
}
json
{
  "spacing": {
    "density": {
      "$value": [
        {
          "value": 1,
          "features": {
            "density": "comfortable"
          }
        },
        {
          "value": 1.2,
          "features": {
            "density": "spacious"
          }
        },
        {
          "value": 0.8,
          "features": {
            "density": "compact"
          }
        }
      ],
      "$description": "",
      "$type": "number"
    }
  }
}

Configuration

config.js
js
import 
StyleDictionary
from 'style-dictionary';
import {
isConstrainedByPlatform
,
isConstrainedToken
,
isCSSProperty
,
matchesConstraints
,
registerTheemo
} from '@theemo/style-dictionary';
registerTheemo
(
StyleDictionary
);
function
makeDensityPlatform
(
density
) {
return {
transformGroup
: 'theemo',
buildPath
: 'build/',
constraints
: {
features
: {
density
:
density
} },
options
: {
outputReferences
: true,
showFileHeader
: false
},
files
: [
{
format
: 'css/variables',
destination
: `density-${
density
}.css`,
filter
:
isConstrainedByPlatform
} ] }; } /** @type import("style-dictionary/types").Config */ export default {
source
: ['tokens/**/*.json'],
preprocessors
: ['theemo/token'],
platforms
: {
css
: {
transformGroup
: 'theemo',
buildPath
: 'build/',
options
: {
outputReferences
: true,
showFileHeader
: false,
useCSSColorTransform
: true
},
files
: [
{
format
: 'css/properties',
destination
: 'properties.css',
filter
:
isCSSProperty
}, {
format
: 'css/variables',
destination
: 'vars.css',
filter
: (
token
) =>
// when no CSS property !
isCSSProperty
(
token
) &&
// and matches color-scheme constraint (
matchesConstraints
(
token
, {
features
: {
'color-scheme': ['light', 'dark'] } }) || // but no other constraint !
isConstrainedToken
(
token
))
} ] }, // constrained tokens (to combine them later under given selectors) 'density-comfortable':
makeDensityPlatform
('comfortable'),
'density-spacious':
makeDensityPlatform
('spacious'),
'density-compact':
makeDensityPlatform
('compact')
} };

Output

css
@property --palette-brand-red {
  syntax: "<color>";
  inherits: true;
  initial-value: #e41b1b;
}

@property --palette-brand-yellow {
  syntax: "<color>";
  inherits: true;
  initial-value: #ffec40;
}

@property --sizing-base {
  syntax: "<length>";
  inherits: true;
  initial-value: 1em;
}

@property --sizing-ratio {
  syntax: "<number>";
  inherits: true;
  initial-value: 1.3;
}

/* ... more @property ... */
css
:root {
  --brand-text: var(--palette-brand-yellow);
  --brand-background: var(--palette-brand-red);
  --layout-background: light-dark(var(--palette-structure-white), var(--palette-structure-200));
  --palette-brand-500: var(--palette-brand-red);
  --palette-brand-100: hsl(from var(--palette-brand-500) h s calc(l - 40));
  --palette-brand-200: hsl(from var(--palette-brand-500) h s calc(l - 30));
  --palette-brand-300: hsl(from var(--palette-brand-500) h s calc(l - 20));
  --palette-brand-400: hsl(from var(--palette-brand-500) h s calc(l - 10));
  --palette-brand-600: hsl(from var(--palette-brand-500) h s calc(l + 10));
  --palette-brand-700: hsl(from var(--palette-brand-500) h s calc(l + 20));
  --palette-brand-800: hsl(from var(--palette-brand-500) h s calc(l + 30));
  --palette-brand-900: hsl(from var(--palette-brand-500) h s calc(l + 40));
  --intent-action-base-text: var(--palette-letters-brand-highlight);
  --intent-action-base-background: var(--palette-brand-500);
  --intent-action-base-border: var(--intent-action-base-background);
  --intent-action-disabled-text: hsl(from var(--intent-action-base-text) h s l / 0.65);
  --intent-action-disabled-background: hsl(from var(--intent-action-base-background) h s l / 0.65);
  --intent-action-disabled-border: hsl(from var(--intent-action-base-border) h s l / 0.65);
  /* ... more tokens ... */
}
css
:root {
  --spacing-density: 1;
}
css
:root {
  --spacing-density: 1.2;
}