Design Token-Based UI Architecture
以前、Andreas Kutschmann 氏が書いた「Design Token-Based UI Architecture」を読んだことがあります。
最近ふとその内容を思い出したので、あらためて自分の UI 設計の考え方と重ね合わせて整理してみました。
Design Token-Based UI Architecture とは
原著では、UI を次の 3 種類のトークンで構築する考え方が紹介されています。
- Option Tokens
— UI で利用可能なスタイルの選択肢そのものを定義するトークン - Decision Tokens
— Option Tokens の中から「文脈に応じてどのスタイルを使うか」を決めるトークン - Component Tokens
— Decision Tokens を参照し、「どのコンポーネントのどこにスタイルを適用するか」を定義するトークン
デザイントークンをベースとして、コンポーネントのPropsもトークンで設計する感じです。 例えば、Buttonだとvariantとして"primary"や"secondary"のようなインターフェースにする感じです。
私なりの考え方:3 層構造で UI を整理する
原著の考え方はとても理解しやすいのですが、実際のプロダクト開発で扱いやすい形に落とし込むと、
私は UI を以下の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 で直接ユーティリティを大量に書けてしまう環境 によって、
「どのスタイルを使うべきか」という一貫性が少しずつ失われている気がしたためです。
そこで、上記の考え方を試験的に試してます。