Sジブンノート

Design Token-Based UI Architecture

以前、Andreas Kutschmann 氏が書いた「Design Token-Based UI Architecture」を読んだことがあります。
最近ふとその内容を思い出したので、あらためて自分の UI 設計の考え方と重ね合わせて整理してみました。

Design Token-Based UI Architecture とは

原著では、UI を次の 3 種類のトークンで構築する考え方が紹介されています。

  1. Option Tokens
    — UI で利用可能なスタイルの選択肢そのものを定義するトークン
  2. Decision Tokens
    — Option Tokens の中から「文脈に応じてどのスタイルを使うか」を決めるトークン
  3. Component Tokens
    — Decision Tokens を参照し、「どのコンポーネントのどこにスタイルを適用するか」を定義するトークン

デザイントークンをベースとして、コンポーネントのPropsもトークンで設計する感じです。 例えば、Buttonだとvariantとして"primary"や"secondary"のようなインターフェースにする感じです。

私なりの考え方:3 層構造で UI を整理する

原著の考え方はとても理解しやすいのですが、実際のプロダクト開発で扱いやすい形に落とし込むと、
私は UI を以下の3層構造で整理するのが現実的だと感じています。

  1. デザイントークン層(最小単位の値)
  2. アトミックコンポーネント層(唯一トークンを直接参照する層)
  3. ドメインコンポーネント層(アプリ固有 UI)

1. デザイントークン層

UI の「最小単位の値」を定義する層です。

  • 色(プリミティブ / セマンティック)
  • スペーシング
  • 角丸(radius)
  • タイポグラフィ
  • 影・エレベーション

これらは Figma のバリアブルを Single Source of Truth として扱います。

Tokens Studio を使うと、

  • トークンを JSON として抽出
  • GitHub に PR を自動生成
  • フロント側では CSS 変数として利用

というワークフローを組むこともできるはずです。(昔作った記憶あるけど忘れました)

2. アトミックコンポーネント層(Component Tokens に相当)

デザイントークンを 唯一直接参照する UI コンポーネント層 です。

例:

  • Button / TextField / Select
  • Heading / Text
  • Flex / Grid / Box / Container

使用側は生のトークン値に触れず、抽象化された API で UI を構築します。

// OK(抽象化された API を利用)
<Button size="md" variant="primary" />
<Flex gap="sm" bg="primary" />

// NG(トークンの生値を直接使用している)
<Button padding="16px" bg="#0070f3" />
<Flex gap="4px" bg="#0070f3" />

なぜ抽象化するのか?

  • "16px" のような生値ではなく、sm / md / lg のような意味単位で扱える
  • トークン変更時の影響範囲を この層に閉じ込める ことができる
  • Figma の Variant と揃えやすく、MCP との連携も自然
  • 利用側が「どの値を使うべきか」を迷わなくなる

内部はトークン、外部は抽象化された API という設計が理想です。

3. ドメインコンポーネント層(アプリ固有 UI)

アトミックコンポーネントを組み合わせて構築する、プロダクト固有の UI 層です。

例:

  • ShopItemCard
  • UserProfile
  • CheckoutForm

特徴は デザイントークンに直接アクセスしない という点で、これをルールとして強制します。

この構造がもたらすメリット

3 層に分けることで、UI のトークンのデータフローは一方向になります。

Figma → デザイントークン → アトミックコンポーネント → ドメインコンポーネント

この構造により、

  • トークン変更の影響範囲が予測しやすい
  • VRT / Playwright で UI 差分を検出しやすい
  • UI の一貫性が自然と保たれる
  • デザイナーとエンジニアの連携が取りやすい

というメリットが得られます。

私ならどう構築するか(現実的な選択肢)

案 A: Chakra UI に 1〜2 層を任せる

  • Variant ベースの設計が強力
  • ただし emotion 採用が気になる場合は注意

案 B: tailwind + shadcn + 自作アトミックコンポーネント

  • emotion を使わずに済む構成
  • Layout / Typography などの基礎部分だけ自作する運用が現実的

終わりに

この記事を書こうと思った理由は、個人開発で tailwind + shadcn を使って UI を作っているうちに、
className で直接ユーティリティを大量に書けてしまう環境 によって、
「どのスタイルを使うべきか」という一貫性が少しずつ失われている気がしたためです。
そこで、上記の考え方を試験的に試してます。