zudo-doc
GitHub リポジトリ

検索したい単語を入力

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

テーマパック

作成 2026年7月16日更新 2026年7月21日Takeshi Takatsudo

カラースキームシステムの上に重なるインストール可能なデザインバンドル — 同梱パック、スイッチャー UI、zudo-doc theme CLI。

テーマパックは、スタイルシート・メタデータファイル・オプションのセルフホストフォントをひとまとめにした、インストール可能なデザインバンドルです。デザイントークン、フォントスタック、コンポーネントのディテールまで、サイト全体の見た目を一手で切り替えます。パックは @takazudo/zudo-doc に同梱されており、設定フィールド 1 つで選択でき、オプションのページ内スイッチャーからライブで切り替えることもできます。

テーマパックとカラースキームの違い

zudo-doc のテーマ機構は 2 つのレイヤーからなり、両者は契約上独立しています:

  • カラースキームはランプネイティブなライト/ダークのパレットです — colorScheme/colorMode 設定フィールド、ヘッダーのモードトグル、light-dark() による解決がこの層に属します。サイトにとっての「ライト」「ダーク」が何色なのかを決めるのはこの層です。Color を参照してください。

  • テーマパックはその上に重なるインストール可能なデザインバンドルです。パックはデザイントークンを上書きし、フォントスタックを差し替え、コンポーネントを再スタイルできます — そしてすべての色を light-dark() でライト/ダーク両方定義するため、既存のモードトグルはどのパックの上でもそのまま機能します。

パックを切り替えてもライト/ダークの状態には触れませんし、モードをトグルしてもアクティブなパックには触れません。

カラースキーム(モードシステム)テーマパック
設定フィールドcolorSchemecolorModethemePackthemePackSwitcherthemePacks
DOM 属性<html data-theme><html data-theme-pack>
永続化キーlocalStorage["zudo-doc-theme"]localStorage["zudo-doc-theme-pack"]
変更イベントcolor-scheme-changedtheme-pack-changed

Note

単独の「テーマ」という語は、常にライト/ダークのモードシステムを指します。パック層の語彙はすべてテーマパックです — data-themecolor-scheme-changed はテーマパック API の一部ではなく、パックがこれらを読み書きすることもありません。

同梱パック

@takazudo/zudo-doc には 31 のパックが同梱されています — 各パックのバッジ・フォント・適用スニペットを載せた全カタログはテーマギャラリーにあります。コレクションの中で特別な役割を持つのは次の 2 つです:

スラッグ説明
defaultzudo-doc 標準の見た目。予約されたパックで、メタデータのみを同梱します — このパックのスタイルシートが読み込まれることは決してないため、標準の見た目に追加リクエストは一切発生しません。
foundryリファレンスパック。GitHub ニュートラルなベースライン — 白い紙面、ほぼ黒のインク、Primer ブルーのリンク — で、9 つの --zd-syntax-* コードハイライトロールを含むすべてのトークン面を、ライト/ダーク両モードで再スタイルします。

パックの選択

この機能は 3 つの設定フィールドで制御します:

フィールドデフォルト役割
themePack"default"アクティブなパックのスラッグ。
themePackSwitcherfalse右下のスイッチャーフライアウト(と一覧ダイアログ)を全ページにマウントする。
themePacksundefined有効化するパックのスラッグをスイッチャー順で並べたリスト。undefined は同梱パックすべて — "default" が先頭、残りはアルファベット順。
zfb.config.ts
export default defineConfig(
  zudoDoc({
    siteName: "My Docs",
    themePack: "foundry",
    themePackSwitcher: true,
    themePacks: ["default", "foundry"],
  }),
);
  • 明示的な themePacks リストが正となります。"default" を省いても構いませんし、その並び順がそのままスイッチャーの Prev/Next の巡回順と一覧ダイアログのグリッド順になります。

  • themePackthemePacks に未知のスラッグや重複したスラッグがあると、プラグインのセットアップ時点でビルドが大きな声で失敗し、問題のスラッグと利用可能なスラッグの一覧が表示されます。ビルド時のサイレントフォールバックはありません。

  • themePackSwitcherfalse のままにして themePack に default 以外のパックを指定することもできます。切り替え UI を持たない、ビルドで固定された見た目です。

スイッチャー UI

themePackSwitcher: true にすると、ビューポート右下に小さな丸いランチャーボタンが固定表示されます。クリックするとフライアウトカードが開き、アクティブなパックの名前、Light/Dark バッジ(そのパックが主に想定するモード)、説明文に加えて、次の操作が並びます:

  • Prev / Next — 有効なパックを themePacks の順で巡回します(末尾で折り返し)。

  • 一覧表示(グリッドアイコン)— 後述のグリッドダイアログを開きます。

  • ✕ / Esc — カードを閉じます。

カードの表示は切り替えが実際にコミットされたときだけ進みます — パックのスタイルシートの読み込みに失敗した場合、現在のパックが適用されたままで UI も動きません。

一覧ダイアログ

グリッドダイアログには有効なパックごとに 1 枚のカードが並びます — ミニプレビュー(見出しサンプル、本文の 1 行、そのパックのシンタックスカラーで彩色されたコード行)、パック名、Light/Dark バッジ、説明文です。2 つの挙動は意図的なものです:

  • 一覧表示のためのダウンロードはゼロ。 カードは各パックのメタデータに含まれる解決済みプレビュースウォッチから、現在のライト/ダークモードに合わせて描画されます — カタログ全体を眺めても、パックのスタイルシートも Web フォントも一切取得されません。

  • 適用してもダイアログは開いたまま。 カードをクリックするとそのパックが即座にページへ適用されますが、ダイアログは開いたままなので、見た目を並べて比較できます。閉じるのは Esc、✕ ボタン、または背景クリックです。アクティブなカードには選択リングが付き、どの UI から切り替えても追従します。

永続化とランタイム挙動

  • 読者の選択は localStorage["zudo-doc-theme-pack"] に保持され、描画前のブートストラップが再適用します — ハードロードでも最初のフレームから正しいパックで描画され(デフォルトの見た目が一瞬見えるフラッシュはありません)、SPA ナビゲーションもまたぎます。JavaScript 無効の訪問者には設定された themePack が表示されます。

  • 保存済みスラッグが有効なパックでなくなった場合(パックの削除、タイプミス、改竄)は、設定された themePack へ静かにフォールバックします。

  • ダウンロードされるのは常にアクティブなパックの CSS とフォントだけです — 切り替え時は次のパックのスタイルシートを取得し、読み込み完了を待ってからアトミックに切り替わります。default パックは何も読み込みません。

  • テストや連携向けの契約: アクティブなスラッグは常に <html data-theme-pack="…"> から読み取れ、コミットされた切り替えのたびに window 上で theme-pack-changed イベント(detail: { pack, previous })が発火します。

theme CLI

@takazudo/zudo-doczudo-doc bin には theme サブコマンドがあります。完全オフラインで動作します — カタログはインストール済みパッケージから、アクティブなパックはプロジェクトの zfb.config.ts から読み取り、ネットワークには何も取りに行きません。

# list the installed packs and which one is active
pnpm exec zudo-doc theme list

# switch the project to the foundry pack
pnpm exec zudo-doc theme apply foundry

theme list は、インストール済み各パックのスラッグ・名前・モード・バージョン・説明を表示し、プロジェクトが現在設定しているパックに印を付けます。

theme apply <slug> の挙動:

  • まずスラッグをインストール済みカタログに対して検証します — 未知のスラッグは、利用可能なスラッグの一覧とともに拒否されます。

  • zfb.config.tszudoDoc({ … }) 呼び出し内の themePack フィールドを書き換えます。フィールドがなければ追加します。

  • 設定が正規のスキャフォールド形でない場合(たとえば設定がスプレッドの向こうに隠れている場合)はきっぱり拒否します — 理由を説明し、手作業で加えるべき 1 行を提示し、中途半端な編集は決して書き込みません。

  • 冪等です — すでに設定済みのスラッグを再適用してもファイルは変わりません。

  • プロベナンス(スラッグ、パックのバージョン、タイムスタンプ)を .zudo-doc.json に記録します。zudo-doc eject が使うのと同じ、遅延生成されるファイルです。

パック指定でのスキャフォールド

create-zudo-doc は、同梱パックのどれを起点にしたプロジェクトでも生成できます — --theme-pack <slug> フラグ、または対話式の「Theme pack:」プロンプト(カラースキームの質問と機能のマルチセレクトの間に表示されます)で指定します。スイッチャー UI は独立した機能トグルです。create-zudo-doc CLI リファレンスを参照してください。

pnpm create zudo-doc my-docs --theme-pack foundry --theme-pack-switcher

ライト/ダークと Design Token Panel

  • パックの Light/Dark バッジは、そのパックがどちらのモードを主として設計されたかのヒントであって、対応可否のフラグではありません。すべてのパックが両モードを定義しており、ヘッダーのモードトグルはどのパックでも同じように機能します。

  • Design Token Panel の調整はパックごとに保存されます。パック A がアクティブなときに保存した上書きはパック A に紐づき、別のパックの間は隠れ、A に戻すとそのまま復元されます。default パックではパネルは従来のストレージを使い続けるため、テーマパック導入以前に保存した調整はアップグレード後もそのまま生き残ります。

パックの作り方

パックは theme-packs/<slug>/ という 1 つのディレクトリで、pack.cssmeta.json、オプションの fonts/ フォルダを持ちます。meta.json はパックのアイデンティティ(スラッグ、表示名、説明、Light/Dark バッジ、バージョン)に加えて、一覧ダイアログがカードを描画するための解決済みプレビュースウォッチを運びます。

theme-packs/my-pack/pack.css
html[data-theme-pack="my-pack"] {
  --zd-bg: light-dark(#ffffff, #0d1117);
  --zd-accent: light-dark(#0969da, #4493f8);
  --zd-syntax-keyword: light-dark(#cf222e, #ff7b72);
  --font-sans: "Jost", system-ui, sans-serif;
  --zdc-doc-title-weight: 600;
}

オーサリング契約の要点:

  • すべてのルールを html[data-theme-pack="<slug>"] でスコープする。 これが切り替えをアトミックにし、非アクティブなパックがスタイルを漏らさないことを保証します。

  • すべての色を light-dark(lightValue, darkValue) で両モード定義する。 パックは color-scheme: を宣言せず、[data-theme] セレクタも使いません — モードはあくまでトグルの仕事です。

  • 上書きするのは --zd-* セマンティックロール(9 つの --zd-syntax-* ハイライトロールを含む)--zdc-* コンポーネントシーム。 --color-* の Tailwind エイリアスは決して上書きしません — Design Token Panel のライブ編集ラウンドトリップが壊れます。

  • 追加の装飾は安定した DOM フックに対してのみheader[data-header]#desktop-sidebar[data-admonition]pre.hi-root など)— Tailwind ユーティリティクラス名に対しては決して書きません。

  • --font-sans は今やクローム全体をスタイルします。プロズだけではありません。 レイヤー化されていない body { font-family: var(--zdc-chrome-font, var(--font-sans)) } というシームが、各パックの --font-sans をヘッダー・サイドバー・目次・パンくず・フッターへと届けます — かつては .zd-content にしか届かなかった上書きが、今はアプリシェル全体に届きます。パックが用意すべきものは一貫した --font-sans ひとつだけで、あとはシームがそれをすべての面に自動的に届けます。--zdc-header-font--zdc-sidebar-font--zdc-toc-font は、いずれかのシェルサーフェスだけをあえて他と異なる書体にしたいパックのためのオプションのフックです(コンポーネントトークンを参照)— ほとんどのパックはこれらを設定しません。サイドバー/目次のトークンはデスクトップとモバイルのクロームの両方に届きます。セレクタはデスクトップのレールとモバイルのドロワー/目次の両方を指定しており、本番ビルドでは両方とも一致します(Preactのハイドレーションは、それらのモバイルアイランドがレンダリングするSSR済みのdata-*属性を保持します)。zfbの開発サーバーpnpm dev)はアイランドのルート要素からdata-*属性を取り除くため、pnpm dev実行中はモバイル側が一致しません — この開発/本番間の不整合は#2898で追跡されています。サーフェスごとのサイドバー/目次専用フォントは、開発サーバーではなくビルドに対して検証してください。

  • フォントはセルフホストの OFL ライセンス Google Fonts かシステムスタックのみ。 font-display: swap を付け、フォールバックスタックは必ず総称ファミリーで終端します。商用フォントを前提にすることも参照することもありません(local("Futura") のような記述は禁止)— Futura 風のパックは OFL の代替である Jost を読み込みます。これにより、すべてのパックがオフライン(Tauri リーダー)でも厳格な CSP の下でも同一に描画されます。

ビルド時のバリデーターがこの契約全体 — スコープ、トークン名のマニフェスト、フォントの整合、商用フォントの拒否リスト — を強制するため、壊れたパックはパッケージのビルドを失敗させ、あなたのサイトのビルドを壊すことはありません。アーキテクチャの全容(メタデータスキーマ、切り替えアルゴリズム、バリデータールール)は theme-packs ADR に確定仕様として記録されています。

関連項目

Revision History

Takeshi Takatsudo作成: 2026-07-16T19:18:54+09:00更新: 2026-07-21T13:17:40Z

AI Assistant

Ask a question about the documentation.

Preview theme

Loading theme previews…