Zudo Token Panel
GitHub リポジトリ

検索したい単語を入力

いつでも検索バーを開ける

トークン階層(タブマニフェスト)

TabConfig・TierConfig・TierItem・TierValueKind・PillSpec・ColorClusterExtras — パネルの編集可能タブを定義するすべての型。

コンセプト概要

このページは、ティアモデルを型ごとに正確に定義するリファレンスです。まず設計上の意図と、リテラルティアと参照ティアの関係を理解したい場合は、アーキテクチャを先にお読みください。

パネルは、PanelConfig.tabs として渡される TabConfig オブジェクトのフラットな配列からタブストリップをレンダリングします。各タブは、編集可能な行からなる 1 つ以上のティアを保持します。ティアはリテラル値を保持することも、別のティアのアイテムへの参照を保持することもできます。このページでは、ティアモデルのすべての公開型を正確に定義します。

TierValueKind

行にどのエディターウィジェットが表示されるかを制御する、判別可能なユニオン型(discriminated union)です。

export type TierValueKind =
  | { kind: 'length'; step: number; unit: string }
  | { kind: 'number'; step: number }
  | { kind: 'select'; options: readonly string[] }
  | { kind: 'text' }
  | { kind: 'color' }
  | { kind: 'cursor' }
  | { kind: 'content' }
  | { kind: 'mask-image' };
kind説明エディター追加で必須のフィールド
'length'単位付きの寸法値単位サフィックス付きのテキスト入力(例: rempxstepunit
'number'単位なしの数値制約のないテキスト入力step
'select'定義済みの選択肢セットドロップダウンoptions(空でない文字列配列)
'text'自由形式の CSS 式(イージングカーブ、フォントファミリー、生の文字列)自由形式のテキスト入力
'color'カラー値 — カラータブのパレットティアで使用カラーピッカー
'cursor'cursor プロパティの値(pointercrosshair などのキーワード、または url(...) <fallback>自由形式のテキスト入力
'content'疑似要素向けの content プロパティの値(引用符付き文字列、nonenormalurl(...)、生成コンテンツ関数)自由形式のテキスト入力
'mask-image'mask-image プロパティの値(noneurl(...)、グラデーション関数)自由形式のテキスト入力

特定の TierConfig.items 配列内のすべてのアイテムは、同じ kind を共有しなければなりません(MUST)。1 つのティア内で kind を混在させると、バリデーション時に拒否されます。

PillSpec

単一の TierItem のメイン入力を補完する、オプションのピルトグルです。

export interface PillSpec {
  /** Sentinel value emitted when the pill is ON (e.g. `"9999px"` for border-radius-full). */
  value: string;
  /** Default CSS value used when the pill is OFF and no override is active. */
  customDefault: string;
}

TierItempill を持つ場合、ティアリゾルバーはオーバーライドマップを次のように解釈します。

  • オーバーライドが pill.value と等しい → ピルのセンチネル値をそのまま出力します。

  • オーバーライドなし → item.default ではなく pill.customDefault をベースラインとして使用します。

  • item.default が使われるのは、オーバーライドも customDefault もどちらも適用されない場合のみです。

TierItem

ティア内の 1 つの編集可能な行です。

export interface TierItem {
  /** Stable id used as the key in persisted state. Rename = state loss. */
  id: string;
  /** CSS custom property written to `:root` (must start with `--`). */
  cssVar: string;
  /** Human-visible label rendered in the panel row. */
  label: string;
  /** Default CSS string value — used when no override is active. */
  default: string;
  /** Discriminated union controlling the edit widget. */
  type: TierValueKind;
  /** Opt-in sentinel-value toggle. */
  pill?: PillSpec;
  /** Display-only flag — the row is rendered but not editable. */
  readonly?: true;
}

`group` フィールドなし

TierItem.group(ティア内のサブ見出しキー)は #148 で削除されました。パネルの1 ティア 1 見出しポリシーにより、各ティアはちょうど 1 つのセクション見出しをレンダリングする必要があります。概念的にサブグループ分けが必要なティアは、代わりに複数の TierConfig エントリに分割します。サンプルマニフェストで group を参照してはいけません。

フィールドリファレンス

フィールド必須備考
idYes永続化されたオーバーライドマップにおける安定したキー。名前を変更すると、legacyIdRenameMap を設定していない限り既存のユーザー状態が壊れます。
cssVarYes:root に書き込まれる CSS カスタムプロパティ。-- で始まり、プレフィックスの後が空でない必要があります。assertValidPanelConfig によって検証されます。
labelYesパネル行内の表示ラベル。
defaultYesオーバーライドが有効でないときに出力されるフォールバックの CSS 文字列。
typeYesこの行にどのエディターがレンダリングされるかを制御します。
pillNoメインエディターと並べて、オプトインのセンチネルトグルを追加します。
readonlyNotrue の場合、行は表示されますが編集不可となり、apply パイプラインからスキップされます。

TierConfig

タブ内の TierItem エントリの名前付きグループです。

export interface TierConfig {
  /** Stable id — must be unique within the parent `TabConfig`. */
  id: string;
  /** Human-visible label (e.g. "Raw values", "Semantic"). */
  label: string;
  /** The editable rows this tier owns. All items must share the same `kind`. */
  items: readonly TierItem[];
  /**
   * When set, this tier holds cross-tier references.
   * Each item's override value is interpreted as the id of an item in the
   * tier named by this field. The apply pipeline emits
   * `var(--that-tier-item-cssVar)` rather than the raw value string.
   */
  referencesTier?: string;
  /**
   * Marks this tier as a SEMANTIC tier on the Color tab — its items hold
   * `SemanticValue` mappings (index, literal, per-mode literal, or a
   * cross-tab ramp reference) rather than raw palette entries, so the
   * panel never mistakes it for the palette tier even when its items are
   * `kind: 'color'`. A tier with `semantic: true` and no sibling palette
   * tier is a **lone semantic tier** — the Color tab renders it with no
   * palette grid at all. Additive: omitting `semantic` preserves the
   * pre-#459 structural palette-detection behavior.
   */
  semantic?: true;
  /**
   * Cross-tab ramp-source declaration for a `semantic: true` tier owned by a
   * tab whose id is exactly `color` or `color-secondary`; other owning tab
   * ids are rejected. Each entry names an allowed source tier `id` and an
   * optional source `tab` id (omitted `tab` means "this tab"). Validated up
   * front by `assertValidPanelConfig` before any row renders.
   */
  referencesRamps?: readonly { tab?: string; tier: string }[];
}

referencesTier を持つティアは参照ティアと呼ばれます。そのアイテムは直接の CSS 値を保持せず、別の(リテラル)ティア内のソースアイテムの id を保持します。referencesTier の値は、同じ TabConfig 内に存在するティアの id でなければなりません。ティアの kind は一致している必要があります(例: 両方とも 'color'、または両方とも 'length')。

semantic と referencesRamps はカラータブの概念

semantic はカラータブの概念です。referencesRamps を使用できるのは、id が正確に 'color' または 'color-secondary' である TabConfig 内のティアだけであり、それ以外の親タブ id は assertValidPanelConfig によって拒否されます。完全な動作契約 — SemanticValue ユニオン、単独セマンティックティアのレンダリング方法、タブ間の実例 — については、カラークラスターを参照してください。

TabConfig

最上位の単位 — パネルのストリップにおける 1 つのタブです。

export interface TabConfig {
  /** Stable id. Reserved ids dispatch to built-in tab components. */
  id: string;
  /** Human-visible tab label. */
  label: string;
  /** Ordered tiers rendered inside the tab. */
  tiers: readonly TierConfig[];
  /**
   * Color-tab metadata. Required for the reserved `'color'` and
   * `'color-secondary'` ids — ignored (and unnecessary) for all other ids.
   */
  colorExtras?: ColorClusterExtras;
}

`advancedTiers` フィールドなし

TabConfig.advancedTiers(タブごとの「Advanced」<details> 開閉)は #148 で削除されました。パネルのプログレッシブディスクロージャー禁止ポリシーにより、すべてのティアは折りたたみセクションなしでフラットにレンダリングされる必要があります。タブに多数のトークンがある場合は、代わりにティアセクション順にフラットにレンダリングします。サンプルマニフェストで advancedTiers を参照してはいけません。

予約済みタブ id

idディスパッチ先
'color'プライマリカラータブ — パレット + ベースロール + セマンティックテーブル。colorExtras が必須。
'color-secondary'セカンダリカラータブ。colorExtras が必須。
'font'タイポグラフィタブ。
'spacing'スペーシングタブ。
'size'サイズタブ。
その他の任意の文字列GenericTab — kind に応じたエディターを使ってタブの tiers をレンダリングします。

ColorClusterExtras

カラータブが必要とする、ティア以外のメタデータです。予約済みカラー id を持つタブの TabConfig.colorExtras に配置します。

export interface ColorClusterExtras {
  /** Stable id forwarded to the internal ColorClusterDataConfig bridge. */
  id: string;
  /** Optional label for Color-tab section headings. Falls back to `id.toUpperCase()`. */
  label?: string;
  /** CSS custom-property names for base terminal roles. */
  baseRoles: Partial<Record<BaseRoleKey, string>>;
  /** Fallback palette indices when a scheme omits a base role. */
  baseDefaults: Partial<Record<BaseRoleKey, number>>;
  /** Fallback shikiTheme name when a scheme lacks one. */
  defaultShikiTheme: string;
  /** Bundled color-scheme registry keyed by display name. */
  colorSchemes: Record<string, ColorScheme>;
  /** Panel-level scheme settings (seed scheme, optional light/dark mode). */
  panelSettings: ClusterPanelSettings;
}

export type BaseRoleKey = 'background' | 'foreground' | 'cursor' | 'selectionBg' | 'selectionFg';

例: 単一ティアの spacing タブ

1 つのリテラルティアを持つシンプルなタブです。すべてのアイテムが length トークンです。

import type { TabConfig } from '@takazudo/zdtp';

export const spacingTab: TabConfig = {
  id: 'spacing',
  label: 'Spacing',
  tiers: [
    {
      id: 'base',
      label: 'Base spacing',
      items: [
        { id: 'sp-xs', cssVar: '--myapp-spacing-xs', label: 'XS', default: '0.25rem', type: { kind: 'length', step: 0.125, unit: 'rem' } },
        { id: 'sp-sm', cssVar: '--myapp-spacing-sm', label: 'SM', default: '0.5rem',  type: { kind: 'length', step: 0.125, unit: 'rem' } },
        { id: 'sp-md', cssVar: '--myapp-spacing-md', label: 'MD', default: '1rem',    type: { kind: 'length', step: 0.25,  unit: 'rem' } },
      ],
    },
  ],
};

例: 2 ティアの easing タブ(リテラル + 参照)

セマンティックティアが raw ティアを参照するジェネリックタブです。パネルはセマンティックアイテムに対して、生の cubic-bezier 文字列ではなく var(--myapp-easing-ease-in) を出力します。

import type { TabConfig } from '@takazudo/zdtp';

export const easingTab: TabConfig = {
  id: 'easing',
  label: 'Easing',
  tiers: [
    {
      id: 'raw',
      label: 'Raw values',
      items: [
        { id: 'ease-in',    cssVar: '--myapp-easing-ease-in',    label: 'Ease in',    default: 'cubic-bezier(0.42, 0, 1, 1)', type: { kind: 'text' } },
        { id: 'ease-out',   cssVar: '--myapp-easing-ease-out',   label: 'Ease out',   default: 'cubic-bezier(0, 0, 0.58, 1)', type: { kind: 'text' } },
        { id: 'ease-inout', cssVar: '--myapp-easing-ease-inout', label: 'Ease in-out',default: 'cubic-bezier(0.42, 0, 0.58, 1)', type: { kind: 'text' } },
      ],
    },
    {
      id: 'semantic',
      label: 'Semantic aliases',
      // referencesTier causes the apply pipeline to emit var(--myapp-easing-*)
      // rather than the raw cubic-bezier string.
      referencesTier: 'raw',
      items: [
        { id: 'tab-open',  cssVar: '--myapp-transition-tab-open',  label: 'Tab open',  default: 'ease-in',    type: { kind: 'text' } },
        { id: 'tab-close', cssVar: '--myapp-transition-tab-close', label: 'Tab close', default: 'ease-out',   type: { kind: 'text' } },
        { id: 'modal',     cssVar: '--myapp-transition-modal',     label: 'Modal',     default: 'ease-inout', type: { kind: 'text' } },
      ],
    },
  ],
};

この構成では、tab-open'ease-out' にオーバーライドすると、apply パイプラインはリテラルのイージング文字列ではなく --myapp-transition-tab-open: var(--myapp-easing-ease-out) を出力します。

関連ページ

Revision History

作成更新