一键导入
style-dictionary-pipeline
Building a Style Dictionary v4+ pipeline with platform transforms and CI publishing. Use this when setting up or evolving the token build.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Building a Style Dictionary v4+ pipeline with platform transforms and CI publishing. Use this when setting up or evolving the token build.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Android adaptive icons and iOS app icon light/dark/tinted modes. Use this when creating or revising app launcher icons.
Cross-platform icon pipeline — SVG source, Android VectorDrawable, SF Symbols, Flutter/RN delivery, sizing, and parity. Use this when adding or refactoring the icon set.
Scalable, theme-aware illustrations for mobile — pipeline, tokenization, and platform delivery. Use this when authoring or shipping illustrations.
Structuring a cross-platform component library into primitives, patterns, and compositions with predictable folder layout and public API. Use this when starting or reorganizing a component library.
Slots, compound components, and headless primitives for flexible mobile component APIs. Use this when a component needs to serve many callers without becoming a grab-bag of props.
Modeling component variants as a closed matrix of size × intent × state, with explicit enums and slot APIs. Use this when designing or refactoring a component's public API.
| name | style-dictionary-pipeline |
| description | Building a Style Dictionary v4+ pipeline with platform transforms and CI publishing. Use this when setting up or evolving the token build. |
Style Dictionary is the canonical build for DTCG tokens. It takes JSON in, produces Kotlin, Swift, Dart, and TypeScript out, and runs on every PR. Configure it once, treat outputs as generated code.
design-system/
├── tokens/
│ ├── reference/**/*.json
│ ├── system/**/*.json
│ └── component/**/*.json
├── scripts/
│ ├── style-dictionary.config.mjs
│ └── transforms/
│ ├── duration.mjs
│ ├── cubic-bezier.mjs
│ └── typography.mjs
├── build/ # generated — gitignored
│ ├── android/
│ ├── ios/
│ ├── flutter/
│ └── rn/
└── package.json
// scripts/style-dictionary.config.mjs
import StyleDictionary from 'style-dictionary';
import { registerTransforms as registerTokensStudio } from '@tokens-studio/sd-transforms';
import './transforms/duration.mjs';
import './transforms/cubic-bezier.mjs';
import './transforms/typography.mjs';
registerTokensStudio(StyleDictionary);
export default {
source: ['tokens/**/*.json'],
platforms: {
compose: {
transformGroup: 'compose',
transforms: ['attribute/cti', 'name/cti/pascal', 'color/composeColor',
'size/dp', 'size/sp', 'duration/ms-to-number', 'cubicBezier/array'],
buildPath: 'build/android/',
files: [{
destination: 'DsTokens.kt',
format: 'compose/object',
options: { packageName: 'com.ds.tokens', className: 'DsTokens' },
}],
},
ios: {
transformGroup: 'ios-swift',
transforms: ['attribute/cti', 'name/cti/camel', 'color/UIColorSwift',
'size/swift/remToCGFloat', 'duration/ms-to-double'],
buildPath: 'build/ios/',
files: [{ destination: 'DSTokens.swift', format: 'ios-swift/class.swift',
options: { className: 'DSTokens' } }],
},
flutter: {
transformGroup: 'flutter',
buildPath: 'build/flutter/',
files: [{ destination: 'ds_tokens.dart', format: 'flutter/class.dart',
options: { className: 'DsTokens' } }],
},
rn: {
transformGroup: 'js',
buildPath: 'build/rn/',
files: [
{ destination: 'tokens.ts', format: 'javascript/es6' },
{ destination: 'tokens.d.ts', format: 'typescript/es6-declarations' },
],
},
},
};
DTCG ships types Style Dictionary does not natively handle. Write small transforms and register them.
// scripts/transforms/duration.mjs
import StyleDictionary from 'style-dictionary';
StyleDictionary.registerTransform({
name: 'duration/ms-to-number',
type: 'value',
matcher: t => t.$type === 'duration',
transformer: t => parseInt(String(t.$value).replace('ms', ''), 10),
});
StyleDictionary.registerTransform({
name: 'duration/ms-to-double',
type: 'value',
matcher: t => t.$type === 'duration',
transformer: t => parseFloat(String(t.$value).replace('ms', '')) / 1000,
});
// scripts/transforms/cubic-bezier.mjs
StyleDictionary.registerTransform({
name: 'cubicBezier/array',
type: 'value',
matcher: t => t.$type === 'cubicBezier',
transformer: t => t.$value, // already [x1,y1,x2,y2]
});
For composite types (typography, shadow), a custom format emits idiomatic platform code.
StyleDictionary.registerFormat({
name: 'compose/object',
formatter({ dictionary, options }) {
const { packageName, className } = options;
const lines = dictionary.allTokens.map(t =>
` val ${t.name}: ${composeType(t)} = ${composeLiteral(t)}`);
return `package ${packageName}\n\nobject ${className} {\n${lines.join('\n')}\n}\n`;
},
});
Before Style Dictionary builds, validate tokens:
component/* token aliases a reference/* token.color.surface.* / color.content.*.{...} references.// scripts/validate.mjs
import { validate } from './validators/index.mjs';
await validate({ sources: ['tokens/**/*.json'] });
Fail the build on any violation.
Either run Style Dictionary N times (one per theme × brand) or use @tokens-studio/sd-transforms with sets/modes.
const combos = [
{ name: 'light', sets: ['reference', 'system.light'] },
{ name: 'dark', sets: ['reference', 'system.dark'] },
{ name: 'acme-light', sets: ['reference', 'brand/acme', 'system.light'] },
{ name: 'acme-dark', sets: ['reference', 'brand/acme', 'system.dark'] },
];
for (const combo of combos) {
await buildFor(combo);
}
Output to build/<combo>/<platform>/.
pnpm build:tokens on every PR; fail on diff between committed and generated outputs.com.ds:ds-tokens:X.Y.Z) from build/android/.build/ios/ — push a tag.pub.dev or private pub from build/flutter/.@ds/tokens@X.Y.Z to the registry.build/ — rewritten on next run.duration, cubicBezier, typography, shadow.build/<combo>/ directories.