デザイントレンド

規模での設計システムにおける色:Shopify、GitHub、およびAtlassianからのレッスン

1分で読める

すべての設計システムは最終的に色の危機に直面します。通常、小さく始まります。新しい製品の表面には、パレットに存在しない色が必要です。ダークモード要件はコンポーネント全体での色の使用方法に矛盾を公開します。または、リブランディングは、色トークンが数十のファイル全体に散在していることを明らかにします。明確な階層がありません。これらの問題を最も公開的に解決しているチーム — Shopify、GitHub、およびAtlassian — は、彼らのアプローチを十分に詳細で文書化しており、パターンを比較し、任意のサイズのシステムに適用される原則を抽出できます。

これは、その文書の要約ではありません。彼らが行った決定、これらの決定が解決した問題、および自分のシステムのために借りることができるものの分析です。


Shopify Polaris:トークン層モデル

Polarisは、存在する最も成熟した公開設計システムの1つです。Shopifyは2017年以来これを反復しており、何千ものShopifyマーチャント、アプリ開発者、および内部製品チームに役立ちます。色は彼らが解決する必要があった最も複雑な問題の1つです — Shopifyのブランドパレットが複雑であるためではなく、すべての一貫して「Shopify」と感じるべき表面、アプリ、およびコンテキストの膨大な数です。

名前の付いた色からロールベースのトークンへ

Polarisの初期バージョンでは、比較的簡単なパレット名の色を使用していました。チームは --p-color-green-400 をコンポーネントに直接プルできました。これが機能していない限り、それは機能しました。ダークモードはすべてのコンポーネントで条件付きロジックなしに実装することは不可能でした。Polarisトークンを使用するアプリ開発者は、Shopify管理者の更新中に壊れるコンポーネントを構築しました。新しいプリミティブが正当化される場合と、セマンティック割り当てが再利用される場合、明確なルールは存在しません。

Polaris v12は、これらの問題に対処した3段階のトークンモデルを導入しました。

層1 — 色スケール:利用可能なすべての色の数値スケール。色相と明るさステップで名前が付けられました。これらはソース-真実のプリミティブです。Shopifyは、ほとんどの色相に13ステップのスケール(非常に軽いから非常に暗い)を使用し、内部トークン定義のみのためにこれらのトークンを予約します — アプリ開発者は直接使用することが期待されていません。

層2 — ロールトークン:層1値を参照する目的の名前の付きトークン。これはコンポーネント作成者が使用するものです。--p-color-bg-surface--p-color-text-critical--p-color-border-interactive のような名前は、その色がどのように見えるかではなく、色がしていることを説明しています。

層3 — コンポーネントトークン:ロールトークンを参照するコンポーネント範囲のトークン。ボタンの背景は --p-color-bg-fill-brand で、ライトモードでは --p-color-green-600 にマップされます。ダークモードでは --p-color-green-400 にマップされます。コンポーネントは、どのグリーン値を使用しているかを決して「知る」ことはありません。

Polarisがダークモードをどのように処理するか

Polarisは、同じロールトークン名から2つの完全なトークンセット — ライトモードとダークモード — を生成します。割り当てファイルは構成のように読まれます。

bg-surface (light): color-scale-neutral-50    → #F6F6F7
bg-surface (dark): color-scale-neutral-900    → #1A1A1A

出力は、同一の変数名を持つが、異なる値を持つ2つのCSSファイルです。ダークモードは、ダークトークンファイルを読み込むこと(またはルート要素の data-polaris-color-scheme 属性を切り替えることによって)適用されます — コンポーネントスタイルシートでダークモード上書きを記述することではありません。

これがアーキテクチャの洞察です。ダークモードはコンポーネント例外の集合ではありません。それは異なるセマンティック割り当てのセットです。

Polarisから借りるもの

「色を定義するもの」を「色を使用するもの」から分離することは、Polarisの最も重要なパターンです。色スケールの決定は、深い色の専門知識を持つ小さなグループによって行われます。ロールトークン割り当ては、目的を理解する設計システムデザイナーによって行われます。コンポーネント使用法は、スケールと割り当ての決定の両方からシールドされている任意の製品開発者によって処理されます。色の決定へのアクセス制御 — ポリシーではなくアーキテクチャを通じて — は、大規模なチームが一貫性をどのように維持するかです。


GitHub Primer:複製なしで色モード

GitHubのPrimer設計システムは、ほとんどのシステムが持っていない課題に直面しています。ライトモード、ダークモード、ダーク暗くされたモード、ダーク高コントラストモード、およびライト高コントラストモードで同じインターフェースを役立つ必要があります。それは5つの完全な色モードで、すべてGitHubのように感じる必要があります。

per-Mode上書きの問題

5つの色モードへのナイーブなアプローチは、5つのCSSオーバーライドセットを書きます — 各モードの1つ。結果は数千行の反復的なCSS、指数関数的に成長するテスト表面、およびシステムが進化するにつれて不一貫性の確実性です。1つのモードで色を変更し、その色の対応する値が他のモードで一貫しないかどうかを知るシステマティックな方法はありません。

Primerはすべての5つのモードを同じセマンティックスキーマのインスタンスとして扱うことによってこれを解決します。すべてのセマンティックロールには5つの値があります — モードごとに1つ — 単一のデータ構造に保存されています。ビルドシステムは、単一のソース真実からモード固有のCSSを生成します。

Primerの機能色語彙

Primerは、予測可能な名前の機能カテゴリに意味的なトークンを組織します。

fg.default          — プライマリテキスト、アイコン、ボーダー
fg.muted            — セカンダリテキスト、微妙なアイコン
fg.subtle           — プレースホルダーテキスト、無効なアイコン

canvas.default      — ページ背景
canvas.overlay      — ドロップダウン、モーダル背景
canvas.inset        — 引っ込まされた表面、コードブロック

border.default      — デフォルトボーダー
border.muted        — 微妙な仕切り線
border.subtle       — ヘアラインセパレータ

accent.fg           — インタラクティブテキスト(リンク)
accent.emphasis     — 塗りつぶされたインタラクティブ要素(選択したタブ)
accent.muted        — アクセント背景
accent.subtle       — 非常に軽いアクセント色合い

success.fg          — 成功テキスト
success.emphasis    — 成功が満たされた(緑バッジ)
success.muted       — 成功背景色合い
success.subtle      — 非常に軽い成功色合い

この語彙はモード全体で同一に適用されます。ライトモードの success.emphasis#1F883D。ダークモードでは #3FB950。ダーク高コントラストモードでは #56D364。セマンティックな意味 — 「満たされた成功インジケータ」 — はすべてのモード全体で保存されます。値だけが各モードのバックグラウンドコンテキストでアクセシビリティを維持するために変更されます。

スケール透明性

Primerは、その完全な色スケールを公開します。すべてのプリミティブ — blue-000 #DBF4FF から blue-900 #0A192F まで — は文書化されています。公開スケールは、2つの目的に役立ちます。GitHubのAPIの上に構築されているアプリ開発者にビジュアル語彙を理解させます。Primerチームをセマンティック割り当てが行われる前に、スケール完全性について説明責任を保持しています。

設計システムの一般的な失敗モード は、参照するプリミティブの良い候補を持たないセマンティックトークンを作成することです — スケールには正しいシェードがないため、誰かがスケールの外側に落ちる1回限りの16進値を追加します。Primerのアプローチはこれを見えるようにします。セマンティック割り当てがスケールに含まれていない色を必要とする場合、スケールはバイパスされるのではなく拡張される必要があります。

色アクセシビリティはモード生成に組み込まれています

Primerは、トークン生成パイプラインの一部としてWCAGコントラストチェックを実行します。生成されたすべてのモードは、モードが受け入れられる前にテキスト背景とアイコン背景の組み合わせのための最小コントラスト閾値を通す必要があります。これはアクセシビリティ回帰テストが手動ではなく構造的であることを意味しています — 開発者は、ビルドが失敗しなくなる新しいモードまたはスケール変更を送信することはできません。

これはあらゆるシステムで複製する価値があります。ビルドステップのコントラストチェック、設計レビューステップではなく、高圧配信サイクル中にアクセシビリティはスリップできないことを意味しています。


Atlassian設計システム:トークンはAPI

Atlassianの設計システムは、Jira、Confluence、Trello、Bitbucket、および成長するForgeアプリのエコシステムに役立ちます。トークンモデルは明示的に、製品チームとサードパーティ開発者が依存できる安定したAPIとして枠組み付けられています。 — トークンの名前を変更せずにトークンの値を変更すると、任意の製品のビジュアル設計に意味のある方法で壊すことはできません。

明示的なトークン契約

Atlassianは、契約に達する量のトークン説明を公開します。color.background.neutral のようなトークンは、単に「中立的な背景」と文書化されていません — それは明示的な保証で文書化されています。このトークンは常に中立的な(無彩色またはほぼ無彩色)背景色になります。常に上に配置されたテキスト行 color.text に対してWCAG AA コントラストを満たします。ライトモードとダークモードで常に利用可能になります。

これらの保証は、製品チームがすべての新しいテーマリリースをテストせずにトークンを使用できることを意味します。システムチームはその約束と引き換えにテスト負担を吸収します。

この明示的な契約モデルはトークン命名に意味のある意味を持っています。特定のテキスト色に対して常に十分なコントラストを持つと約束するトークンは、コントラストが無関係な装飾的な用途のために再利用することはできません。名前は契約を理解可能にするのに十分に具体的である必要があります。

Atlassianの命名分類法

Atlassianは4つのセグメントを持つ構造化された命名分類法を使用します。

color . {category} . {variant} . {state}

color.text.subtle               不安なテキスト無状態=デフォルト
color.text.subtle.[hovered]     ホバーされた状態上書き
color.background.selected       選択された表面
color.border.focused            フォーカスリング色
color.icon.danger               危険アイコン色

括弧記法 [hovered] は、状態トークンがオプションであることを示しています — コンポーネントはそれを適用するかもしれません、またはしないかもしれません。必要な基本トークンには括弧がありません。

移行戦略:シームを太くする

Atlassianは、レガシー製品を生の16進値からトークンに移行する必要があります。彼らが公開した移行戦略は、「シームを太くする」と呼ばれるものを含みます — 移行中に色分けされたオーバーレイがある理由で、トークン境界を可視化するのではなく、静かにリファクタリングしようとしています。

彼らのツーリングは、すべてのトークン領域を、要素がトークンを使用しているかどうかを示すビジュアル監査モードを生成します(グリーン)、レガシーハードコード値を使用します(イエロー)、または非推奨のトークンを使用します(赤)。製品チームは各リリース前にこの監査を実行して、移行進捗を追跡します。

実践的なレッスン:設計システムの移行が進行可能で見える場合に成功します。色トークンは、特に視覚的な監査ツーリングに適しています。データはリテラリーは画面上で見えるためです。


3つのシステム全体で共通のパターン

Polaris、Primer、およびAtlassianを比較すると、同じベストプラクティスの独立した発見であるように見える一貫した決定が明らかになります。

プリミティブとセマンティック層の分離

3つのシステムすべてが、生の色値(プリミティブ)と目的の名前のトークン(セマンティック)の間に厳密な境界を維持しています。コンポーネントコードはプリミティブを参照していません。この分離により、テーマ、ダークモード、およびリブランディングをコンポーネントコードに触れることなく可能にします。

セマンティック名はロール説明、色相説明ではない

3つのシステムのいずれもセマンティックトークン名で色相単語を使用しません。「強調」、「微妙」、「消音」、「重大」、「表面」、「キャンバス」 — これらの単語は、色がしていることを説明しています。実際の色相は、プリミティブレイヤーに住む実装の詳細です。

アクセシビリティはビルド制約

3つのシステムすべてが、ドキュメントではなく、ツーリングパイプラインでアクセシビリティ要件を強制します。コントラスト閾値は自動的にチェックされます。これにより、アクセシビリティが良い意図から機械的な保証に移ります。

マルチモード支援はアーキテクチャ

ダークモード(およびPrimerの場合、5つのモード)は同じセマンティック スキーマから複数のトークン値セットを生成することで処理されます。これは prefers-color-scheme をコンポーネントコードでオーバーライドを記述することで処理されていません。このアーキテクチャの分離により、コンポーネント作成者がユーザーが選択したモードについて完全に認識されないようになります。


大規模チームの色の決定をスケーリング

色のアーキテクチャの組織的な側面は、技術的な側面と同じくらい重要です。大規模なチームは、色の決定に対して明確な所有権構造が必要であり、これらの構造はトークン構造自体でエンコードされるべきです。

色の決定の3つのレベル

スケール決定(プリミティブパレット内に存在する色)は、最も専門知識を必要とします — 色科学の知識、ブランド専門知識、およびアクセシビリティテスト。これらの決定はめったに行われず、システム全体に影響します。所有権:設計システムコアチーム。

セマンティック割り当ての決定(このプリミティブはどのような目的を提供するか)は、製品コンテキストとユーザーの期待を理解する必要があります。これらの決定は、新しい製品表面が追加されるか、設計方向の大きな変化がある場合に発生します。所有権:製品設計主導の入力を持つシステムの設計。

使用決定(どのセマンティックトークンがこの特定の要素にこの特定のコンテキストに適用されます)は、最小の専門知識を必要とし、特別なアクセスがありません。トークン名を読むことで、任意のデザイナーまたは開発者は自信を持ってこれらの決定を行うことができるべきです。所有権:個々の製品チーム。

トークンアーキテクチャはこの階層をエンコードします。セマンティック割り当てファイルにのみ表示されるプリミティブトークンは建築的に保護されています。明確な名前のセマンティックトークンは自己サービスです。これはポリシー制御ではなく、建築的なガイダンスです。

新しいトークンが正当化される場合

3つのシステムすべてが、新しいトークンを追加する場合と既存のトークンを再利用する場合の基準を開発しました。新しいセマンティックトークンは、以下の場合に正当化されます。

  • 新しい目的が真に存在して、現在のトークンはカバーしません
  • 新しい目的は少なくとも3つの異なるコンポーネントに表示されます
  • 目的は既存のトークンの構成として表現することはできません(例えば、不透明度のあるトークン)
  • 追加は既存のトークン語彙に対してレビューされており、異なる名前のトークンを複製しないことを確認しています

「3つのコンポーネント」閾値は、トークン語彙がすべてのエッジケースの1回限りのトークンで無制限に成長するのを防ぎます。同様の目的の統合を強制し、セマンティック層を理解可能に保ちます。


今日実装すること

設計システムの色レイヤーを構築またはリファクタリングしている場合、チームサイズに関係なく、ここは実践的なスタートシーケンスです。

  1. セマンティックロールの割り当てを開始する前に、プリミティブパレットを完全に定義します。数値または名前のスケールを使用して、各色相の全範囲をカバーします。

  2. 既存のコンポーネントコードを監査して、実際の色ロールを発見します — 何を意図したかではなく、実際に何が起こっているか。コンポーネント全体で目的でグループ化します。

  3. 監査からセマンティックトークン名を下書きします。色相言語ではなく、ロール言語(表面、テキスト、ボーダー、フィードバック)を使用します。

  4. プリミティブをセマンティックスにマップします。マッピングにスケールに存在しないプリミティブが必要な場合、オフスケール値を使用するのではなく、スケールを拡張します。

  5. 最も一般的なテキスト背景の組み合わせに対して、自動コントラストチェックを追加します。

  6. 一度に1つのコンポーネントを移行し、トークンベースの値を使用します。遷移中のレガシーコードに対してプリミティブを利用可能に保ちます。

ここで説明されているシステムはスプリントで構築されていません。彼らはこの種の反復作業を吸収し、実際の製品の失敗からレッスンを吸収することによって進化しました。彼らが共有しており、彼らのアプローチを転送可能にする理由 — は、色の決定を専門知識で分離し、規則ではなくアーキテクチャとして表現される必要があるコア原則です。

関連カラー

関連ブランド

関連ツール