mcpField
S
style-dictionary

style-dictionary

github.com/dylantarre设计与 UI5047 次安装43 周前更新
代码仓库

关于 style-dictionary

style-dictionary 是一项设计令牌配置技能,指导将单一来源的令牌转换为面向不同平台的代码格式。它涵盖自定义转换与输出格式、多主题配置及构建流程集成。

主要功能

  1. 01从令牌源生成平台专属输出
  2. 02转换颜色、尺寸等令牌值
  3. 03配置自定义转换与输出格式
  4. 04设置多主题和多品牌令牌
  5. 05集成令牌构建流程

适用场景

  1. 01为 Web、iOS 和 Android 输出设计令牌
  2. 02将 Figma 导出的令牌转换为代码
  3. 03在构建流程中自动生成令牌文件
  4. 04扩展令牌转换或输出格式

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/dylantarre/design-system-skills --skill style-dictionary

安装后在 Claude Code 中输入/style-dictionary确认已加载。

详细介绍

Style Dictionary

概述

设置 Style Dictionary,将设计令牌转换为特定平台的格式。这是设计系统领域的行业标准,可从单一令牌源生成适用于 Web、iOS、Android 及其他平台的内容。

适用场景

  • 为需要支持多个平台的新设计系统进行设置
  • 将 Figma 令牌转换为代码
  • 从同一来源生成 CSS、SCSS、iOS Swift、Android XML
  • 添加自定义令牌转换或格式
  • 将令牌集成到构建流水线中

快速参考:核心概念

概念用途示例
令牌带有元数据的设计值{ "value": "#3b82f6", "type": "color" }
转换转换令牌值color/hex → color/rgb
格式输出到文件类型CSS 变量、Swift、XML
平台目标环境web、ios、android

流程

  1. 评估令牌来源:令牌定义在哪里?(Figma、JSON、YAML)
  2. 确定平台:哪些平台需要令牌?
  3. 设置配置:创建 style-dictionary.config.js
  4. 定义转换:添加任何自定义值转换
  5. 构建:运行 style-dictionary build
实施清单

设置 Style Dictionary 时复制此清单:

Style Dictionary Setup:
- [ ] Install: `npm install style-dictionary`
- [ ] Create tokens/ directory with source JSON files
- [ ] Create style-dictionary.config.js with source paths and platform outputs
- [ ] Add build script to package.json: `"tokens:build": "style-dictionary build"`
- [ ] Run build and verify output files are generated correctly

项目设置

安装
npm install style-dictionary
# or
yarn add style-dictionary
目录结构
tokens/
├── base/
│   ├── colors.json
│   ├── spacing.json
│   └── typography.json
├── semantic/
│   ├── colors.json
│   └── components.json
└── themes/
    ├── light.json
    └── dark.json

build/                    # Generated output
├── css/
│   └── variables.css
├── ios/
│   └── StyleDictionary.swift
└── android/
    └── colors.xml

style-dictionary.config.js

配置

基本配置
// style-dictionary.config.js
module.exports = {
  source: ['tokens/**/*.json'],
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'build/css/',
      files: [
        {
          destination: 'variables.css',
          format: 'css/variables',
        },
      ],
    },
  },
};
多平台配置
// style-dictionary.config.js
module.exports = {
  source: ['tokens/**/*.json'],

  platforms: {
    // Web - CSS Custom Properties
    css: {
      transformGroup: 'css',
      buildPath: 'build/css/',
      files: [
        {
          destination: 'variables.css',
          format: 'css/variables',
          options: {
            outputReferences: true, // Keep token references
          },
        },
      ],
    },

    // Web - SCSS Variables
    scss: {
      transformGroup: 'scss',
      buildPath: 'build/scss/',
      files: [
        {
          destination: '_variables.scss',
          format: 'scss/variables',
        },
      ],
    },

    // Web - JavaScript/TypeScript
    js: {
      transformGroup: 'js',
      buildPath: 'build/js/',
      files: [
        {
          destination: 'tokens.js',
          format: 'javascript/es6',
        },
        {
          destination: 'tokens.d.ts',
          format: 'typescript/es6-declarations',
        },
      ],
    },

    // iOS - Swift
    ios: {
      transformGroup: 'ios-swift',
      buildPath: 'build/ios/',
      files: [
        {
          destination: 'StyleDictionary.swift',
          format: 'ios-swift/class.swift',
          className: 'StyleDictionary',
        },
      ],
    },

    // Android - XML Resources
    android: {
      transformGroup: 'android',
      buildPath: 'build/android/',
      files: [
        {
          destination: 'colors.xml',
          format: 'android/colors',
          filter: { type: 'color' },
        },
        {
          destination: 'dimens.xml',
          format: 'android/dimens',
          filter: { type: 'dimension' },
        },
      ],
    },
  },
};

令牌格式

Design Tokens Community Group(DTCG)格式
{
  "color": {
    "primary": {
      "$value": "#3b82f6",
      "$type": "color",
      "$description": "Primary brand color"
    },
    "secondary": {
      "$value": "#64748b",
      "$type": "color"
    }
  },
  "spacing": {
    "sm": {
      "$value": "8px",
      "$type": "dimension"
    },
    "md": {
      "$value": "16px",
      "$type": "dimension"
    }
  }
}
Style Dictionary 经典格式
{
  "color": {
    "primary": {
      "value": "#3b82f6",
      "type": "color",
      "comment": "Primary brand color"
    }
  },
  "spacing": {
    "sm": { "value": "8px" },
    "md": { "value": "16px" }
  }
}
令牌引用(别名)
{
  "color": {
    "base": {
      "blue": {
        "500": { "value": "#3b82f6" }
      }
    },
    "primary": {
      "value": "{color.base.blue.500}"
    },
    "button": {
      "background": {
        "value": "{color.primary}"
      }
    }
  }
}

自定义转换

注册自定义转换
// style-dictionary.config.js
const StyleDictionary = require('style-dictionary');

// Transform px to rem
StyleDictionary.registerTransform({
  name: 'size/pxToRem',
  type: 'value',
  matcher: (token) => token.type === 'dimension',
  transformer: (token) => {
    const px = parseFloat(token.value);
    return `${px / 16}rem`;
  },
});

// Transform color to OKLCH
StyleDictionary.registerTransform({
  name: 'color/oklch',
  type: 'value',
  matcher: (token) => token.type === 'color',
  transformer: (token) => {
    // Use a color library like culori
    const { formatCss, oklch, parse } = require('culori');
    return formatCss(oklch(parse(token.value)));
  },
});

module.exports = {
  source: ['tokens/**/*.json'],
  platforms: {
    css: {
      transforms: [
        'attribute/cti',
        'name/cti/kebab',
        'size/pxToRem',      // Custom
        'color/oklch',        // Custom
      ],
      buildPath: 'build/css/',
      files: [
        {
          destination: 'variables.css',
          format: 'css/variables',
        },
      ],
    },
  },
};
常见自定义转换
// Clamp font sizes for fluid typography
StyleDictionary.registerTransform({
  name: 'size/fluidType',
  type: 'value',
  matcher: (token) => token.attributes?.category === 'font' && token.attributes?.type === 'size',
  transformer: (token) => {
    const min = parseFloat(token.value) * 0.875;
    const max = parseFloat(token.value);
    return `clamp(${min}rem, 2vw + 1rem, ${max}rem)`;
  },
});

// Shadow to CSS format
StyleDictionary.registerTransform({
  name: 'shadow/css',
  type: 'value',
  matcher: (token) => token.type === 'shadow',
  transformer: (token) => {
    const { x, y, blur, spread, color } = token.value;
    return `${x}px ${y}px ${blur}px ${spread}px ${color}`;
  },
});

自定义格式

支持深色模式的 CSS
StyleDictionary.registerFormat({
  name: 'css/variables-themed',
  formatter: ({ dictionary, options }) => {
    const lightTokens = dictionary.allTokens
      .filter(t => !t.path.includes('dark'))
      .map(t => `  --${t.name}: ${t.value};`)
      .join('\n');

    const darkTokens = dictionary.allTokens
      .filter(t => t.path.includes('dark'))
      .map(t => {
        const name = t.name.replace('dark-', '');
        return `  --${name}: ${t.value};`;
      })
      .join('\n');

    return `:root {\n${lightTokens}\n}\n\n[data-theme="dark"] {\n${darkTokens}\n}`;
  },
});
Tailwind 配置格式
StyleDictionary.registerFormat({
  name: 'tailwind/config',
  formatter: ({ dictionary }) => {
    const colors = {};
    const spacing = {};

    dictionary.allTokens.forEach(token => {
      if (token.type === 'color') {
        const path = token.path.slice(1).join('-');
        colors[path] = token.value;
      }
      if (token.type === 'dimension' && token.path[0] === 'spacing') {
        spacing[token.path[1]] = token.value;
      }
    });

    return `module.exports = {
  theme: {
    extend: {
      colors: ${JSON.stringify(colors, null, 2)},
      spacing: ${JSON.stringify(spacing, null, 2)},
    },
  },
};`;
  },
});

多主题设置

令牌结构
tokens/
├── core/
│   ├── colors.json      # Primitives (blue-500, gray-100)
│   └── spacing.json
├── semantic/
│   ├── light.json       # Semantic mappings for light
│   └── dark.json        # Semantic mappings for dark
└── brand/
    ├── default.json     # Default brand
    └── partner.json     # White-label brand
主题专属配置
// style-dictionary.config.js
const themes = ['light', 'dark'];
const brands = ['default', 'partner'];

module.exports = {
  source: ['tokens/core/**/*.json'],

  platforms: brands.flatMap(brand =>
    themes.map(theme => ({
      [`css-${brand}-${theme}`]: {
        transformGroup: 'css',
        buildPath: `build/${brand}/`,
        files: [
          {
            destination: `${theme}.css`,
            format: 'css/variables',
            filter: (token) =>
              token.filePath.includes('core') ||
              token.filePath.includes(theme),
          },
        ],
        source: [
          `tokens/semantic/${theme}.json`,
          `tokens/brand/${brand}.json`,
        ],
      },
    }))
  ),
};

构建流水线集成

package.json 脚本
{
  "scripts": {
    "tokens:build": "style-dictionary build",
    "tokens:watch": "style-dictionary build --watch",
    "tokens:clean": "rm -rf build/",
    "prebuild": "npm run tokens:build"
  }
}
与 Figma Tokens 插件配合使用
# 1. Export from Figma Tokens plugin to tokens/figma.json
# 2. Transform with Style Dictionary

npx token-transformer tokens/figma.json tokens/transformed.json
style-dictionary build
GitHub Action
# .github/workflows/tokens.yml
name: Build Tokens

on:
  push:
    paths:
      - 'tokens/**'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm ci
      - run: npm run tokens:build
      - uses: actions/upload-artifact@v4
        with:
          name: tokens
          path: build/

输出示例

输入令牌
{
  "color": {
    "primary": {
      "value": "#3b82f6",
      "type": "color"
    }
  }
}
CSS 输出
:root {
  --color-primary: #3b82f6;
}
SCSS 输出
$color-primary: #3b82f6;
JavaScript 输出
export const ColorPrimary = '#3b82f6';
iOS Swift 输出
public class StyleDictionary {
    public static let colorPrimary = UIColor(red: 0.231, green: 0.510, blue: 0.965, alpha: 1.0)
}
Android XML 输出
<?xml version="1.0" encoding="UTF-8"?>
<resources>
  <color name="color_primary">#3b82f6</color>
</resources>

常见问题与解决方案

问题解决方案
循环引用检查令牌别名是否形成循环
未找到令牌确认引用中的路径完全匹配
输出格式错误检查转换组是否与平台匹配
缺少令牌检查 filter 是否将其排除
构建结果过时构建前运行 tokens:clean

Style Dictionary v4(最新版本)

// style-dictionary.config.js (v4 syntax)
import StyleDictionary from 'style-dictionary';

export default {
  source: ['tokens/**/*.json'],
  preprocessors: ['tokens-studio'], // For Figma Tokens
  platforms: {
    css: {
      transformGroup: 'css',
      buildPath: 'build/',
      files: [{
        destination: 'variables.css',
        format: 'css/variables',
      }],
    },
  },
};
# Run with ESM
node --experimental-json-modules ./node_modules/.bin/style-dictionary build

评论

支持 Markdown