Ubie Design Tokensを公開しました


こんにちは、Ubie株式会社でデザインエンジニアをやっている です。

Ubieではデザインのクオリティと生産性向上のためデザイン生産基盤の整備に力を入れています。
今回その一環として開発したデザイントークンをnpmパッケージとして公開しました。(現在はColorのみ。)

https://www.npmjs.com/package/@ubie/design-tokens

開発経緯

Ubie Design Tokens開発以前からデザイントークンのようなものは存在しており、CSS Variablesとして実装されていました。しかしユースケースを想定せず作った変数があったり定義が細かすぎたりしたことで「どの変数をどういう場面で使用すれは良いかわからない」という問題が発生していました。

そこで変数の定義を見直し、より実際のデザインに即したデザイントークンを策定するとともに、プロダクトごとの実装差異をなくすためのライブラリの開発に着手しました。

Colorの定義

Ubie Design TokensではPrimitive ColorsSemantic Colorsの2種類を定義しています。

Primitive Colorsは色に機械的に名前を付けたもので、ベースになる色セットです。

Primitive Colorsの定義

Semantic Colorsでは色のユースケースごとに名前を付け、Primitive Colorsで定義された色を参照しています。名前だけで利用用途がわかるよう命名しています。

Semantic Colorsの定義

Primitive ColorsSemantic Colorsを分離することで、色の利用用途を明確にできるだけでなく、変更も容易になりメンテナンス性が向上すると考えています。
例えばテキストの黒色のみを変更したい場合、Primitive Colorsのみ定義していた場合はテキストの色として使われている黒を検索して置き換えなければなりませんが、Semantic Colorsも定義されていれば参照先の色を変更するだけで完了します。

実際のCSSの定義は次のようになります。

:root {
  --ubie-blue-700: #263f94;
  --ubie-blue-500: #3959cc;
  --color-primary: var(--ubie-blue-500);
  --color-primary-darken: var(--ubie-blue-700);
}

技術構成

Ubie Design Tokensの技術構成は次のとおりです。

  • Style Dictionary
  • Figma API
  • GitHub Actions

FigmaのStyleに定義したColorの情報をAPI経由でJSON化しStyle DictionaryでCSSなどの各種スタイルを生成する構成になっています。

技術構成

Style Dictionary

Ubie Design TokensではStyle Dictionaryを採用しました。

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

Style DictionaryはAmazonが開発しているライブラリで、JSON形式で定義したスタイルを様々なプラットフォームや言語で利用できる形で出力してくれます。
もともとJSON形式のマスターから各環境向けのスタイルを生成できる仕組みを自作しようかと考えていたのですが、開発コストがかかりすぎることやネイティブアプリ向けのスタイルの出力を自力でやれるほどネイティブアプリ開発の知識がないことなどからStyle Dictionaryを採用しました。

現在はCSSSCSSJSの3タイプのファイルを生成&配布しています。CSSSCSSともにCSS Variables形式で出力しています。(CSS Modulesを採用しているプロジェクトが多いため。)
Tailwind向け設定ファイルの生成は今後対応予定です。

config.json
{
  "source": ["tokens/**/*.json"],
  "platforms": {
    "css": {
      "transformGroup": "css",
      "buildPath": "dist/",
      "files": [
        {
          "destination": "tokens.css",
          "format": "css/variables",
          "options": {
            "outputReferences": true
          }
        },
        {
          "destination": "tokens.scss",
          "format": "css/variables",
          "options": {
            "outputReferences": true
          }
        }
      ]
    },
    "js": {
      "transformGroup": "js",
      "buildPath": "dist/",
      "files": [{
        "destination": "tokens.js",
        "format": "javascript/module"
      }]
    }
  }
}

Figma API経由でStyleを取得する

Ubie Design TokensではFigmaのStyleをもとにStyle Dictionary用JSONを生成しています。

大まかな流れは次のような感じです。

  1. GET /v1/files/:file_key/stylesからStyle一覧を取得
  2. スタイル一覧からnode_idを抜き出して結合&文字列化
  3. GET /v1/files/:key/nodes?ids=${node_idを結合した文字列}でStyleが適用されてるNodeの一覧を取得
  4. 取得したNodeから色の情報を抜き出し、Styleの情報と統合してObjectに格納
  5. JSONとして書き出し

FigmaにはStyle一覧を取得するAPIはあるものの、そのAPIからStyleの詳細情報(色やフォントサイズなど)を取得することはできません。
その代わりそのStyleが使われているNodeのidが返ってくるので、そのidをもとにNodeを取得し、そこからStyleの詳細を抜き出す必要があります。

figma.js
const responseStyles = await fetchFigma("/styles");

const styles = responseStyles.meta.styles;
const nodeIds = styles.map((style) => style.node_id);
const nodeIdsQuery = nodeIds.join(",");

const { nodes } = await fetchFigma(`/nodes?ids=${nodeIdsQuery}`);

詳しくはGitHubのコードを見てください。

Figmaでの定義

Semantic ColorsPrimitive Colorsを参照する構造をFigma上で再現することは現状難しいため、それぞれ別々で定義してSemantic Colorsのdescriptionに参照しているPrimitive Colorsの名前を書くという方法を採用しています。
このdescriptionの情報をもとにSemantic ColorsのJSONを生成しています。


Figmaでの定義方法

今後の展開

今後はSpaceやTypographyなどを追加し、より実用的なデザイントークンにしていきたいと考えています。
特にSpaceはFigmaのStyleに登録できないためFigmaとどう連携するか模索中です。

プロダクト開発への浸透もこれから取り組んでいきます!