Design Token Panel
スペーシング、フォント、サイズ、カラーの各デザイントークンをタブ分けしたパネルでライブ編集し、JSONでエクスポート・AIを介して読み込めるワークフローを提供します。
Design Token Panelは、テーマが提供するすべてのデザイントークンをページ上で編集できるインタラクティブなエディタです。以前のColor Tweak Panel(カラー専用)を置き換え、Palette・Color・Font・Spacing・Sizeの5つのトークン種別をタブ構成でカバーします。さらに統一されたJSONエクスポート/インポート機能を備えており、デザインをまとめてAIアシスタントに渡し、返ってきた結果を読み込むラウンドトリップ運用が可能です。
パネルを有効にする
zfb.config.ts で designTokenPanel を true に設定します:
export default defineConfig(
zudoDoc({
designTokenPanel: true,
// ...
}),
);有効になると、ヘッダーに(検索アイコンの左側に)パレットアイコンが表示されます。クリックするとパネルが開閉し、以前のColor Tweak Panelと同じキーボードショートカットも引き続き利用できます。
Note
設定フィールドは designTokenPanel です。true に設定するとパネルが有効になります。ホスト側の設定ファイルは不要です — designTokenPanelConfigModule で独自のビルダーを指定しない限り、パネルはパッケージのデフォルトビルダー(@takazudo/)を使用します(詳しくは下記のパネルのカスタマイズを参照)。
パネルのカスタマイズ
デフォルトでは designTokenPanel: true にホスト側の設定ファイルは不要です — 注入されるパネルはパッケージのデフォルトビルダー(@takazudo/)を使用し、バンドルされたカラースキームから Palette/Color タブを、同梱のトークンマニフェストから Font/Spacing/Size タブを導出します。
完全にカスタムなパネル(独自のトークンマニフェスト、独自のカラースキーム)を用意するには、buildDesignTokenPanelConfig(mode: "light" | "dark") という名前付きビルダーをエクスポートするモジュールを作成し、designTokenPanelConfigModule にそのパスを指定します — プロジェクトルートからの相対パスで、chromeBindingsModule の契約をそのまま踏襲します:
export default defineConfig(
zudoDoc({
designTokenPanel: true,
designTokenPanelConfigModule: "./src/config/design-token-panel-config.ts",
}),
);このショーケースは、パッケージ所有のブートストラップとパッケージのデフォルトビルダーを使用します。自動注入されるブートストラップに独自のモードスコープなビルダーを読み込ませたい場合にのみ、designTokenPanelConfigModule を設定してください。
5つのタブ
パネルは5つのタブに分かれており、それぞれ単一のトークン種別に集中しています。各タブには担当するトークン以外は表示されないため、色の下までスクロールしてスペーシングにたどり着く必要はありません。
Palette
Paletteタブは、すべてのカラースキームの土台となる、共有される3つのOKLCHランプを公開します(Color を参照):
Base — 5 ストップ(
--palette-base-0…--palette-base-4)、インデックス 0 が最も明るいAccent — 3 ストップ(
--palette-accent-0…--palette-accent-2)State — 4 つの名前付きロール:
danger・success・warning・info(--palette-state-{role})
各ストップは、zdtpネイティブのOKLCH明度/彩度/色相のカーブエディタ上でスウォッチとして表示されます。ストップをドラッグすると、そこから構築されたすべてのセマンティックロールがライブで更新されます — 別途の "Scheme…" プリセットドロップダウンはありません。ランプそのものが編集可能なソースオブトゥルースです。ウォークスルーはカラースキームプレビューを参照してください。
Color
Colorタブはセマンティック→ランプのエディタです。27 行 — 4 つの base ロール(bg・fg・selection-bg・selection-fg)と 23 の --zd-* セマンティックロール — があり、各行は Palette タブのランプ上のストップ、あるいは一部のロールではリテラルの OKLCH オーバーライドに紐付けられています。このタブ自体はランプを持たず、Palette タブの Base / Accent / State の各階層を参照するため、そこでランプストップを編集すると、それを指すすべての行の色が変わります。
Ref 行 — グループ化されたランプのドロップダウン
ほとんどの行は、Base / Accent / State の <optgroup> を持つ <select> としてレンダリングされ、Palette タブのランプのストップごとに 1 つのオプションが並びます。オプションを選ぶと、その行の --zd-* カスタムプロパティが var(--palette-{tier}-{n}) に紐付きます — 解決済みの色ではなく、ライブな CSS 変数参照です — そのため、Palette タブで参照先ストップの L/C/H カーブをドラッグするとページが即座に更新され、Colorタブで何かを選び直す必要はありません。
各 ref 行のドロップダウンの末尾には 「Literal…」 エントリもあり、行をランプから切り離して一度きりの色を固定できます。
Literal 行 — モードごとに AA 調整したオーバーライド
一部のロールは、両モードで共有ランプストップだけでは満たせず(モードごとのリテラルオーバーライドを参照)、デフォルトでリテラル行としてレンダリングされます:Literal… が選択された <select> と、編集可能な OKLCH スウォッチです。どのロールがリテラルで始まるかはスキームによって定義されます — Default Light は現在 7 つ(accentHover・success・danger・warning・info・matchedKeywordBg・matchedKeywordFg)、Default Dark は 3 つ(danger・matchedKeywordBg・matchedKeywordFg)で、danger は両モードでリテラルです。
リテラル行のスウォッチには Per-mode チェックボックスがあります。オンにすると、1 つではなく 2 つの独立した OKLCH フィールド(Light / Dark)が現れます。適用される値は light-dark(<light-value>, <dark-value>) になり、パネルは適用先のルートに color-scheme: light dark を設定するため、ブラウザはアクティブなモードに対応する側を解決します。
マッチキーワード用トークン
検索結果でマッチしたキーワードのハイライト方法を制御する2つのセマンティックカラートークンがあります。これらはリテラル行としてレンダリングされ(ライトとダークで共有 — モードごとのリテラルオーバーライドを参照)、検索ウィジェット(pages/)が検索UIのヒット箇所のスタイリングで参照します。
matchedKeywordBg— マッチしたキーワードの背景に塗られる色。matchedKeywordFg— その背景の上に重なる、マッチしたキーワードの文字色。
モードスコープの編集モデル
Colorタブは常に、現在アクティブなモード(ライトまたはダーク)の紐付けを編集し、パッケージの @takazudo/(または設定済みなら自作の colorSchemes 上書き — Color を参照)のそのモードの ColorScheme.map からシードされます。
ライト/ダークの切り替えで、タブの ref/literal のデフォルトが再シードされます — 新しいモードの紐付けに切り替わります(例:
bgがbase-0↔base-4と入れ替わる)。この背後にある destroy+reconfigure の仕組みは実装を参照してください。Palette・Spacing・Font・Size の編集は、切り替えをまたいでそのまま引き継がれます。 これらのタブはモードに依存しないため、ランプカーブの編集やスペーシングスライダーの変更は、これまでと同様にライト↔ダークをまたいで保持されます。
保存された Color タブのオーバーライドは、スキームおよびモードスコープです。 パッケージのデフォルトビルダーは
panelSettings.colorModeでDefault LightとDefault Darkを対応付けるため、保存された Color オーバーライドはアクティブなスキーム識別子に対してのみ復元されます。一方のモードで行ったオーバーライドがもう一方を再配色することはありません。Palette・Spacing・Font・Size タブは切り替えをまたいで共有されます。
既知の制限
設定レベルでのモードごとのリテラルデフォルトはまだできません。 行のマニフェストデフォルトは単一の文字列なので、(
dangerのような)AA 調整されたモードごとのリテラルは、事前に{light, dark}のペアとして宣言されるのではなく、再構成時にアクティブなモードからシードされます。実行時のモードごとの編集(上記の Per-mode チェックボックス)は影響を受けません — これは設定が開始時のデフォルトとして宣言できる内容を制限するだけです。アップストリームの zdtp#499 で追跡されています。グループ化されたドロップダウン内のランプオプションのプレビューは静的です。 各
<option>は、ライブ更新されるスウォッチではなく、ランプストップのマニフェストデフォルトの色を表示します — Palette タブでストップを編集していても、ドロップダウンのリストにはラベルの横に元の色が表示されたままです。適用される色は正しく、ピッカーのプレビューだけが遅れます。3.0 より前の保存済みエンベロープは壊れて表示されることがあります。 このランプネイティブへの再配線より前は、保存された Color タブのオーバーライドはパレットインデックスの整数として保存されていました。現在の設定に対して読み込むと、インデックスのマッピングは、新しいデフォルトではなくソリッドな黒にフォールバックする zdtp のハイドレーションパスを通ります(アップストリームのバグ zdtp#497)。このアップデート後にセマンティックトークンが黒く表示される場合は、Reset all を一度クリックして古いマッピングをクリアしてください。
Spacing
水平(hsp-*)と垂直(vsp-*)のスペーシングスケールを編集するスライダーです。3xs から 2xl までの各ステップに対応するスライダーがあり、ドラッグに応じて縮んだり伸びたりするライブプレビューを表示します。値はレイアウトが潰れないよう、妥当な最小値にクランプされます。
Font
タイポグラフィスケール用のコントロール:
フォントファミリー選択(プリセットまたはカスタム)
数値テキスト入力による抽象スケールトークン(
2xs→2xl)。CSS値のサニタイズありセマンティックロール(
caption・body・headingなど)のマッピング設定
フォントファミリー入力は、複数スタックのフォールバックを含む任意の有効な font-family 値を受け付けます。無効な値(引用符の不一致、生のJavaScriptなど)は入力確定時に拒否されるため、貼り付けたスニペットによってページが壊れることはありません。
Size
セマンティックなアイコンサイズトークン(icon-xs → icon-lg)や、任意値からセマンティックトークンに昇格したコンポーネント寸法に対応する、ピル型スライダーです。各スライダーは、2階層サイズ戦略で想定されるpx値にスナップします。
キーボードアクセシビリティ
タブの切り替えは標準的なWAI-ARIA Tabsパターンを実装しています:
| キー | 動作 |
|---|---|
← / → | 前/次のタブにフォーカスを移動 |
Home | 最初のタブにフォーカス |
End | 最後のタブにフォーカス |
Enter / Space | フォーカス中のタブをアクティブ化 |
タブは自動アクティブ化方式で、矢印キーでフォーカスを移動するとパネルの表示も切り替わります。各タブ内のすべてのスライダー・セレクト・テキスト入力は Tab で辿れ、すべてのコントロールに可視のフォーカスリングが用意されています。
JSONエクスポート — 既定では差分のみ
パネルヘッダーの Export をクリックすると、エクスポートモーダルが開きます。モーダルには、各タブの現在の状態を表す単一のJSONドキュメントが表示され、タブ ID をキーとする tabs オブジェクトでラップされています。
既定のエクスポートはデフォルトとの差分です — 実際に変更したトークンだけが含まれます。まったく触っていないタブは丸ごと省略され、変更があったタブのなかでも編集したトークンだけが残ります。差分は小さく、diffしやすく、コミットに貼り付けても安定した出力になります。
{
"$schema": "zudo-design-tokens/v3",
"exportedAt": "2026-07-05T12:00:00.000Z",
"tabs": {
"palette": {
"raw": {
"--palette-accent-1": "oklch(0.700 0.158 62)"
}
},
"color": {
"semantic": {
"--zd-bg": { "ref": { "tab": "palette", "tier": "base", "item": "base-3" } },
"--zd-danger": {
"literal": { "light": "oklch(.505 .170 25)", "dark": "oklch(.655 .170 25)" }
}
}
},
"spacing": {
"raw": { "--spacing-hsp-md": "1.25rem" }
}
}
}$schema は、変更されたすべての値がプレーンな文字列またはパレットインデックスの数値である間は zudo-design-tokens/v2 ですが、いずれかの Color タブの行が {ref} または {literal} オブジェクトを持った瞬間に自動的に / へアップグレードします — モードスコープのモデルでは、これは実際の zudo-doc のエクスポートでは通常のことです。ref は Palette タブのランプストップ({tab, tier, item})を指し、literal は単一の OKLCH 文字列か、Per-mode 行の場合は {light, dark} のペアのいずれかです。Load… で再インポートすると、どちらの形状もきれいにラウンドトリップします。
モーダルヘッダーの Show defaults too トグルを有効にすると、完全なトークンツリー(すべてのタブ、すべてのトークン、未変更のデフォルトを含む)を出力できます。テーマの全容を知らないデザイナーやAIに渡すスナップショットが必要な場合は、この形式を使ってください。
JSONから読み込み
Load… ボタンを押すとインポートモーダルが開きます。以前のエクスポートやAIが生成したJSONドキュメントを貼り付けると、パネルは次の処理を行います:
形状を検証(バージョン・既知のキー・値の妥当性)。
不明なキーや不正な値を致命的でない警告として報告。
ドキュメントを現在のデフォルトにマージ。未指定のトークンはデフォルトのまま、明示されたトークンだけが上書きされます。
結果を
localStorageに永続化し、すべてのCSSカスタムプロパティを即時に再適用。
不正なJSONは具体的なエラーメッセージとともに拒否されます。spacing.hsp.md だけを変更するような部分的なインポートも、正規のユースケースとしてサポートされます。
AIワークフロー
差分のみのエクスポートとJSONロードを組み合わせると、チャット型AIとの単純なラウンドトリップが実現できます:
渡したいトークンを編集(触らなくてもOK)。
差分をエクスポートしてJSONをコピー。
AIチャットに貼り付け、自然言語でリクエストを添える。例:
これは現在のデザイントークンの差分です。カラーパレットはそのままに、より温かみがあり、コントラストの強いタイポグラフィスケールに書き換え、JSONだけを返してください。
AIが返したJSONを Load… に貼り付け。
パネルが検証・マージ・反映を即座に行います。結果が気に入らなければ、ヘッダーの Reset all で巻き戻せます。
既定のエクスポートが差分になっているため、AIは気にしているトークンだけを読むことになり、未変更のデフォルトを推理する必要がありません。AIに全体像が必要な場合(例: ゼロから新しいテーマを作らせるとき)にだけ Show defaults too をオンにしてください。
永続化
状態は localStorage のキー zudo-doc-tweak-state-v4 に永続化されます。v4エンベロープは各タブの状態(カラー・スペーシング・タイポグラフィ・サイズ、および任意の汎用タブ)を横並びにした単一オブジェクトです。カラー状態はアクティブなスキームの識別子ごとにキー付けされるため、ライトとダークのスキーム編集を独立して復元できます。
ヘッダーの Reset all をクリックすると、保存済みのパネルオーバーライドがクリアされ、設定済みのデフォルトに戻ります。ストレージ形式とライフサイクルはインストール済みの @takazudo/zdtp パッケージが所有し、zudo-doc 自身は永続化エンベロープを解析・変換しません。
ライト/ダークテーマの切り替えで保存済みの編集が消えることはなく、開いているパネルは切り替えをまたいで開いたままになります。テーマトグルは color-scheme-changed イベントをディスパッチし、ホストはパネルをその場でパッチするのではなく、新しいモード用に destroy して再構成します(実装を参照)。そのため、Color タブの ref/literal のデフォルトは新しくアクティブになったモードに追従し、保存済みの Color オーバーライドもそのモードのスキーム識別子に対して復元されます。Palette・Spacing・Font・Size の編集はそのまま引き継がれます。モードスコープの編集モデルを参照してください。
ストレージプレフィックスの継続性保証
ストレージプレフィックス zudo-doc-tweak は、パッケージのデフォルトビルダー(@takazudo/、このショーケースもそのまま利用しています)に固定されており、変わりません。それ以外の永続化の詳細は @takazudo/zdtp が所有し、リポジトリ内の zudo-doc 互換レイヤーには属しません。
実装
パネルUIは @takazudo/zdtp(zdtp)npmパッケージが提供します。パッケージ所有の DesignTokenPanelBootstrap アイランドと、configurePanel の呼び出し、zfb のナビゲーションライフサイクルへのフック、および後述のモードスコープな destroy+reconfigure の仕組みは @takazudo/ にあります。アイランドは bootstrapDesignTokenPanel(buildDesignTokenPanelConfig) を呼び出します。buildDesignTokenPanelConfig は (mode) => PanelConfig のビルダーであり、これが Color タブをライト/ダークに追従させる仕組みです。アイランドがハイドレートすると、パネルはその副作用として自己マウントされます。
遅延読み込み
@takazudo/zdtp は初期ページバンドルには含まれません。bootstrapDesignTokenPanel はマウント時に小さな暫定クリックリスナーを登録するだけで、実際の import("@takazudo/zdtp")(とそれに続く configurePanel の呼び出し)は、ヘッダーのトリガーが最初に toggle-design-token-panel をディスパッチしたときに実行されます。インポートが解決する前に届いたクリックはキューにためられ、configure完了後に正味1回分の表示/非表示にまとめられるため、すばやい連続クリックが二重に発火することはありません。
保存済みの状態を持つ再訪ユーザーは、そのクリックを待つ必要がありません。マウント時にブートストラップは、アクティブな(パックスコープの)ストレージプレフィックス配下の localStorage を確認し、以下のいずれかが真であれば、操作前に即座に zdtp を読み込みます:
パネルが開いたままだった(
${prefix}-openが"1")トークンオーバーライドが保存されていた(
${prefix}-state*というキーが存在する)オーナーモードのフラグが設定されている(
${prefix}:autoload・${prefix}-elpath-enabled・${prefix}-domtweaker-enabledのいずれか)
${prefix}-open とオーナーモードのチェックはキーを直接指定した参照ですが、${prefix}-state* のチェックだけは、その時点で localStorage に存在するすべてのキーを走査します(プレフィックスで問い合わせるネイティブAPIは存在しないため)。ただし、アクティブなプレフィックスの厳密な語幹で始まるキーだけをヒットとして扱うため、すべてのキー名には目を通しつつも、無関係な別アプリ自身の *-state キーに誤反応することはありません。保存済み状態を持つテーマパックへの切り替えも、同様の即時読み込みを引き起こします。
いずれの経路でも zdtp が読み込まれるまでは、window.zdtp(zdtp が構成完了時にインストールするコンソールAPI)は存在しません。一度読み込まれると、そのページが存続する間はその読み込まれた状態を保ち続けます — トグルイベントは zdtp 自身のリスナーが直接引き継ぎます。この遅延状態に戻るのは、ページを丸ごと再読み込みしたときだけです。
(テーマトグルがディスパッチする)color-scheme-changed イベントのたびに、ブートストラップは新しいモードを読み取り、素早い連続トグルを 1 つのマクロタスクにまとめてから、handle.destroy() に続けて configurePanel(buildDesignTokenPanelConfig(mode)) を呼び出します — zdtp の configurePanel は、構造的に異なる設定でその場で再実行すると例外を投げるため、destroy してから再構成することが、Color タブのモードスコープなデフォルトを差し替える唯一のサポートされた方法です。パネルが開いていた場合は、開いた状態で再マウントされます。
ヘッダーのトリガーボタンは window に toggle-design-token-panel カスタムイベントをディスパッチします。zdtpはこのイベントをネイティブに受け取るため、headerRightItems フィールドでトリガーをカスタマイズしても追加の配線は必要ありません。
設定リファレンス
| 設定 | 型 | 説明 |
|---|---|---|
designTokenPanel | boolean | パネルを有効にします。デフォルトは false。 |
designTokenPanelConfigModule | string | 完全にカスタムなパネル用に buildDesignTokenPanelConfig(mode) をエクスポートするモジュールへの、プロジェクトルート相対パス。デフォルトは undefined(パッケージのデフォルトビルダーを使用)。 |
デフォルトのトークンそのもの(スペーシングスケール・フォントスケール・アイコンサイズ・パレットのエイリアス)は@takazudo/から提供されます。スキャフォールドの後続のsrc/にある@themeブロックはオーバーライドポイントです。カラーランプとマッピングには、パッケージの@takazudo/または自作のcolorSchemes上書き(Colorを参照)を使います。パネルはブラウザ内のコピーを編集するだけで、ソースファイルに書き戻すことはありません。
Tip
気に入った組み合わせが見つかったら、差分をエクスポートしてコミットメッセージやデザインドキュメントに貼り付けてみてください — いま行った変更を再現するもっとも小さな説明になります。