🎨

【デザインシステム】デザイントークンをコード変換する Style Dictionary が超便利

2023/02/12に公開

はじめに

弊社マイベストでは、現在デザインシステムを構築中です。

デザインにはFigmaを使っており、デザイントークンをTokens Studioで管理しています。

  • デザイントークンとは何か、ChatGPTに聞いてみました。

    「デザイントークン」とは、デザインに関連する情報を格納する変数のことです。例えば、色やフォントのサイズなどがあります。これらを使うことで、デザインを一貫性を持って管理することができます。デザインシステムを使うことで、将来の修正や更新もスムーズに行えます。

  • Tokens Studio(少し前まで Figma Tokens という名前でした)については以下に詳しいです。

https://zenn.dev/mi_/articles/453f7594120c9a

そして、デザイントークンをそのまま実装でも使えるように変換して運用しています。
つまりFigma上で使うトークンと実装で使える変数が一致しているため、デザイナーとエンジニアのコミュニケーションがとてもスムーズにできます。

トークンの変換には、AmazonがOSSとして公開しているStyle Dictionaryを使っていて、とても便利だったので、今回はその使い方をご紹介します。

Style Dictionaryとは

JSON形式のデザイントークンを、実装コードとして使える形に変換するものです。
例えば、CSS VariablesやJSのObject形式に変換できます。

https://amzn.github.io/style-dictionary/#/

ベーシックな使い方

ベーシックに使うには、config.jsonを用意します。
一例としては、以下のようにすると、scss形式で、variablesのファイルが生成されます。

// config.json
{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "scss": {
      "transformGroup": "scss",
      "buildPath": "build/scss/",
      "files": [{
        "destination": "_variables.scss",
        "format": "scss/variables"
      }],
    }
  }
}

※別のパターンを設定するには、以下のドキュメントを参考に調整してください。
https://amzn.github.io/style-dictionary/#/config

そしてコマンドを用意して、npm run buildまたはyarn buildすればtokenが生成されます。

// package.json
"scripts": {
  "build": "style-dictionary build"
}

単純な使い方をするにはこれだけで簡単ですが、
組織の運用に合わせてカスタマイズした方が都合が良いと思うので、
ここからカスタマイズ方法をご紹介していきます。

カスタマイズ方法

主なカスタマイズ方法としては、config.jsを用意する、というものが有ります。
configファイルの種類としてjsも使えるので、config.jsonではなく、config.jsを用意することで自由な処理を追加できます。

具体的なカスタマイズ手段はいくつかのregister関数を公式が用意してくれています。

registerTransform
registerTransformGroup
registerFilter
registerFormat
registerTemplate (deprecated)
registerAction
registerParser

https://amzn.github.io/style-dictionary/#/extending?id=extension-functions-in-the-api

今回は、その中から弊社で実際に使っている3つを紹介します。

①registerTransform

トークンの中身をcamelCaseにしたりremにしたりpxにしたりといった変換ができます。
https://amzn.github.io/style-dictionary/#/api?id=registertransform

弊社では、一部トークンの値をstringに変換したり、"px"という文字を消して数値だけ残したりしています。

// config.js
StyleDictionary.registerTransform({
  name: "number-to-string",
  type: "value",
  matcher: (token) => token.type === "fontWeight",
  transformer: (token) => token.value.toString(),
});

module.exports = {
  platforms: {
    js: {
      transforms: ["number-to-string"],
      ...
    }
  }
}

②registerFormat

アウトプットするファイルの形式を変更できます。
https://amzn.github.io/style-dictionary/#/api?id=registerformat

弊社では「余計な値を除いた上で、TSファイルとして扱う」ために、以下のようにしています。

// config.js
StyleDictionary.registerFormat({
  name: "tsFormat",
  formatter: function ({ dictionary, file }) {
    const tokens = minifyDictionary(dictionary.tokens)
    return (
      fileHeader({ file }) +
      "export const theme = " +
      JSON.stringify(tokens, null, 2) +
      " as const;"
    );
  },
});

module.exports = {
  platforms: {
    js: {
      files: [
        {
          format: "tsFormat",
          destination: "theme.ts",
        },
      ]
      ...
    }
  }
}

※公式の以下のコードを参考にしています
https://github.com/amzn/style-dictionary/blob/442a5eccf5eb18edae7877ff96712d189316a6dd/lib/common/formats.js#L231-L235

以下の記事では、コメントをJSDoc形式に変換する方法も紹介されていました。
https://zenn.dev/beijaflor/articles/584eb4e00a5bb3

③registerFilter

アウトプットするtokenをfilteringできます。
https://amzn.github.io/style-dictionary/#/api?id=registerfilter

弊社ではデザイン時にFigma上で使えるカラーパレットをprimitiveColorとして用意していますが、実装時にはセマンティックな名前をつけているため、filterによって除外しています。

// config.js
StyleDictionary.registerFilter({
  name: "only-semantics",
  matcher: (token) => !["primitiveColor", "tokenSetOrder"].includes(token.path[0])
});

module.exports = {
  platforms: {
    js: {
      files: [
        {
          format: "tsFormat",
          destination: "theme.ts",
        },
      ]
      ...
    }
  }
}

さらに応用的に使いたい時は

configファイルだけでは足りない場合、build.js(ファイル名は何でも良いです)を用意して実行できます。
以下のように書くと、好きな処理を入れつつ、buildAllPlatformsでbuild処理を実行できます。

// build.js
const StyleDictionary = require('style-dictionary');
// config.jsonを使いたい時は以下のようにする
// const StyleDictionary = require('style-dictionary').extend(__dirname + '/config.json');


// 何らかの処理

StyleDictionary.buildAllPlatforms();

コマンド実行

node build.js

公式ドキュメントによると、例えば異なるconfigファイルで複数回style-dictionaryを実行したい時などに使えるようです。
https://amzn.github.io/style-dictionary/#/config?id=using-in-node

まとめ

FigmaのデザイントークンをStyle Dictionaryを使ってカスタマイズしたアウトプットにする方法を書きました。
かなり柔軟にカスタマイズできるので、デザインシステムの運用に合わせて出力できると実装時のコミュニケーションがかなり楽になります。
デザインシステム構築の際にはぜひ使ってみてください!

また、今後もデザインシステムやその実装、あるいはNext.jsやGraphQLについて発信していきますので、よければTwitterなども見てみてください。
https://twitter.com/_teppeita

Discussion