OhMyUI! - Style Dictionary
Style Dictionary is the tool that powers the OhMyUI! token system. It takes token definitions written in JSON and compiles them into platform-specific output formats - CSS variables for Angular and React, and Dart constants for Flutter.
Style Dictionary was created by Amazon and is open source. You can find it at storybook.js.org.
Why Style Dictionary
Without Style Dictionary, you would need to manually keep three files in sync:
- A CSS file with custom properties for Angular and React
- A Dart file with constants for Flutter
- The original JSON definitions
Change a color in one place and you have to remember to update the other two. Style Dictionary eliminates this problem entirely - you change the JSON once and rebuild, and every platform gets the updated value automatically.
How it works in OhMyUI!
packages/tokens/
├── src/
│ ├── colors.json ← you edit these
│ ├── spacing.json
│ └── typography.json
├── build/
│ ├── css/
│ │ └── variables.css ← Style Dictionary generates this
│ └── dart/
│ └── tokens.dart ← Style Dictionary generates this
└── sd.config.js ← tells Style Dictionary what to doThe configuration file sd.config.js defines two platforms - css and dart - each with its own output format and destination path.
The token format
Every token in the JSON source files has the same structure:
{
"category": {
"name": {
"value": "the actual value",
"type": "the token type"
}
}
}The type field tells Style Dictionary how to transform the value for each platform. Common types are color, dimension, fontFamily, fontWeight and number.
Example - a color token:
{
"color": {
"primary": {
"500": {
"value": "#6366f1",
"type": "color"
}
}
}
}This compiles to:
/* CSS */
--color-primary-500: #6366f1;// Dart
static const colorPrimary500 = Color(0xFF6366F1);Notice how Style Dictionary automatically converts the hex color to the Color(0xFF...) format that Flutter expects. This is called a transform - Style Dictionary applies different transforms for each platform.
The configuration file
// sd.config.js
export default {
source: ['src/**/*.json'], // read all JSON files in src/
platforms: {
css: {
transformGroup: 'css', // apply the standard CSS transforms
buildPath: 'build/css/', // output directory
files: [
{
destination: 'variables.css',
format: 'css/variables', // wrap everything in :root { }
},
],
},
dart: {
transformGroup: 'flutter', // apply the standard Flutter transforms
buildPath: 'build/dart/',
files: [
{
destination: 'tokens.dart',
format: 'flutter/class.dart', // wrap everything in a Dart class
},
],
},
},
};Transform groups
A transform group is a set of transformations applied to token values before they are written to the output file. Style Dictionary includes built-in transform groups for the most common platforms:
| Transform group | Platform | What it does |
|---|---|---|
css | Angular, React | Converts values to CSS-compatible formats, wraps in :root {} |
flutter | Flutter | Converts colors to Color(0xFF...), converts sizes to doubles |
Building the tokens
Run this command from the packages/tokens directory:
npx style-dictionary build --config sd.config.jsOr from the root of the repository:
cd packages/tokens && npx style-dictionary build --config sd.config.js && cd ../..You must rebuild every time you modify a token source file. The build output in packages/tokens/build/ is committed to the repository so that components can reference it without running the build first.
Adding a new token type
If you need a token type that does not fit into the existing categories, create a new JSON file in packages/tokens/src/:
touch packages/tokens/src/shadows.jsonThen add your tokens following the same structure:
{
"shadow": {
"sm": {
"value": "0 1px 3px rgba(0,0,0,0.12)",
"type": "shadow"
}
}
}Style Dictionary will pick it up automatically on the next build because sd.config.js uses a glob pattern src/**/*.json.