デザインシステム
zudo-docのタイトトークン戦略 — スペーシング、タイポグラフィ、カラーなど。
zudo-docはタイトトークン戦略を採用しています。Tailwindフレームワーク全体をインポートするのではなく、preflightとutilitiesのみを読み込み、デフォルトテーマ層を完全にスキップします。その後パッケージが、小さく意図的なデザイントークンのセットを提供します。このページでは、スペーシング、タイポグラフィ、カラー、角丸、ブレークポイント、レイヤリングの全体像を解説します。
タイトトークン戦略
Tailwind CSSには数百の組み込み値(カラー、スペーシングスケール、フォントサイズなど)が用意されています。テーマ切り替え可能なプロジェクトでは、これらのデフォルト値が問題を引き起こします。ハードコードされた値はテーマ変更を無視し、一貫性を崩します。
scaffold の src/ は、Tailwind の preflight(リセット)と utilities(ユーティリティクラス)のみをインポートした後、パッケージのトークンスタイルシートをインポートします。デフォルトの Tailwind テーマ層は意図的にスキップされます:
@layer zd-preflight, zd-flow;
@import "tailwindcss/preflight" layer(zd-preflight);
@import "tailwindcss/utilities";
@import "@takazudo/zudo-doc/theme.css";
@import "@takazudo/zudo-doc/safelist.css";
@import "@takazudo/zudo-doc/content.css";
@import "@takazudo/zudo-doc/page-loading.css";
@import "@takazudo/zudo-doc/features.css";
/* Override package defaults here when the project needs to. */
@theme {
/* e.g. --color-accent: oklch(0.6 0.2 250); */
}@takazudo/ がデフォルトの @theme トークンを提供します。パッケージのソースである packages/ が唯一の情報源であり、scaffold の後続の空の @theme ブロックは上書きポイントです。出荷されるブロックは --color-*: initial で始まり、プロジェクトのカラートークンを再追加する前に Tailwind のデフォルトパレットを消去します。
Info
これが核となる設計思想です。プロジェクトに必要なものだけを定義する。システム内のすべての値は意図的であり、Tailwindデフォルトの誤使用はすぐに判明します。
利用できるTailwindの語彙
タイトトークン戦略は Tailwind のユーティリティ構文を取り除くものではありません。トークンを持つユーティリティを絞り込みます。MDX やコンポーネントでは以下のプロジェクト語彙を使ってください。
| 機能するもの | 機能しないもの(スタイルなし) |
|---|---|
プロジェクトトークン: text-caption、bg-accent、px-hsp-*、py-vsp-*、w-icon-*、z-modal などの z-index tier | 数値スペーシング: p-4、mt-8、w-64 |
tracking-tight、tracking-normal、tracking-wide、tracking-wider | tracking-tighter、tracking-widest |
rounded、rounded-lg、rounded-full | デフォルトの文字サイズ: text-sm、text-lg |
静的ユーティリティ: flex、grid-cols-3、hidden、... | デフォルトパレット: bg-blue-500(設計上リセットされる) |
任意値: m-[13.37px]、w-[42%] — 完全なエスケープハッチ | shadow-md(存在するのは shadow-lg のみ) |
scaffold は @source のカバレッジと Tailwind の自動検出によって、MDX コンテンツ、src/components/、src/、pages/ を走査します。走査対象外の場所で使ったクラスはスタイルなしのマークアップとして出力されるため、新しいソース位置を導入するときは @source ディレクティブを追加してください。
Tailwind のデフォルト語彙を再有効化するには、tailwindcss/theme をインポートするか、プロジェクトの @theme 上書きブロックに必要なトークンを定義します。値がプロジェクトのデザイン言語の一部なら、ローカルのセマンティックトークンを優先してください。
この語彙を MDX コンポーネントで使う例は、カスタムコンポーネントを参照してください。
スペーシング
zudo-docではスペーシングを水平(hsp)と垂直(vsp)の2軸に分離しています。レイアウトにおいてそれぞれ異なる役割を果たすためです。水平スペーシングはインラインのリズムやガターを制御し、垂直スペーシングはコンテンツの流れやセクション間の余白を制御します。垂直スケールは大きいサイズほど広がり、コンテンツにより多くの余白を与えます。
水平スペーシング(hsp)
| トークン | 値 | 使用例 |
|---|---|---|
hsp-2xs | 0.125rem (2px) | px-hsp-2xs |
hsp-xs | 0.375rem (6px) | px-hsp-xs |
hsp-sm | 0.5rem (8px) | gap-x-hsp-sm |
hsp-md | 0.75rem (12px) | px-hsp-md |
hsp-lg | 1rem (16px) | px-hsp-lg |
hsp-xl | 1.5rem (24px) | px-hsp-xl |
hsp-2xl | 2rem (32px) | px-hsp-2xl |
垂直スペーシング(vsp)
| トークン | 値 | 使用例 |
|---|---|---|
vsp-3xs | 0.25rem (4px) | py-vsp-3xs |
vsp-2xs | 0.4375rem (7px) | py-vsp-2xs |
vsp-xs | 0.875rem (14px) | py-vsp-xs |
vsp-sm | 1.25rem (20px) | gap-y-vsp-sm |
vsp-md | 1.5rem (24px) | py-vsp-md |
vsp-lg | 1.75rem (28px) | py-vsp-lg |
vsp-xl | 2.5rem (40px) | py-vsp-xl |
vsp-2xl | 3.5rem (56px) | py-vsp-2xl |
両軸とも0(0px)とpx(1px)のユーティリティ値も含まれます。
<!-- Horizontal padding + vertical padding -->
<div class="px-hsp-lg py-vsp-md">Content with asymmetric spacing</div>
<!-- Grid with dual-axis gaps -->
<div class="grid gap-x-hsp-md gap-y-vsp-lg">Grid items</div>Tip
hsp-lgは1remですがvsp-lgは1.75remと、垂直軸は大きいサイズほど広がります。これは意図的な設計です。垂直方向の流れには水平方向のリズムより多くの余白が必要です。
要素サイズ
アイコンサイズ
| トークン | 値 | 使用例 |
|---|---|---|
icon-xs | 0.75rem (12px) | w-icon-xs h-icon-xs |
icon-sm | 1rem (16px) | w-icon-sm h-icon-sm |
icon-md | 1.25rem (20px) | w-icon-md h-icon-md |
icon-lg | 1.5rem (24px) | w-icon-lg h-icon-lg |
エレベーション
定義されているシャドウトークンは1つだけです。
| トークン | 値 | 使用例 |
|---|---|---|
lg | 0 10px 15px - | shadow-lg |
タイポグラフィ
フォントサイズ
各セマンティックロールは抽象スケール(--text-scale-*)のステップを参照します。以下は解決後のサイズです。
| トークン | 値 | 使用例 |
|---|---|---|
micro | 0.75rem / 12px | text-micro |
caption | 0.875rem / 14px | text-caption |
small | 1rem / 16px | text-small |
body | 1.2rem / 19.2px | text-body |
title | 1.4rem / 22.4px | text-title |
heading | 3rem / 48px | text-heading |
display | 3.75rem / 60px | text-display |
フォントウェイト
| トークン | 値 | 使用例 |
|---|---|---|
normal | 400 | font-normal |
medium | 500 | font-medium |
semibold | 600 | font-semibold |
bold | 700 | font-bold |
行の高さ
| トークン | 値 | 使用例 |
|---|---|---|
tight | 1.25 | leading-tight |
snug | 1.375 | leading-snug |
normal | 1.5 | leading-normal |
relaxed | 1.625 | leading-relaxed |
字間(Letter Spacing)
4段階のスケールです。大きな見出しには tracking-tight を使うと視覚的に引き締まり、tracking-normal はブラウザのデフォルトにリセットします。tracking-wide / tracking-wider はラベルやスモールキャップスのテキストに適しています。
| トークン | 値 | 使用例 |
|---|---|---|
tight | -0.025em | tracking-tight |
normal | normal | tracking-normal |
wide | 0.05em | tracking-wide |
wider | 0.1em | tracking-wider |
フォントファミリー
| トークン | スタック | 使用例 |
|---|---|---|
sans | システムサンセリフスタック | font-sans |
mono | システムモノスペーススタック | font-mono |
<h1 class="text-heading font-bold leading-tight">Page Title</h1>
<p class="text-body font-normal leading-normal">Body text</p>
<code class="text-small font-mono">inline code</code>角丸(Border Radius)
| トークン | 値 | 使用例 |
|---|---|---|
DEFAULT | 0.25rem (4px) | rounded |
lg | 0.5rem (8px) | rounded-lg |
full | 9999px | rounded-full |
<button class="rounded bg-accent text-bg">Default radius</button>
<div class="rounded-lg bg-surface">Card with larger radius</div>
<span class="rounded-full bg-muted">Pill badge</span>ブレークポイント
| トークン | 値 | 使用例 |
|---|---|---|
sm | 640px | sm:flex |
lg | 1024px | lg:grid-cols-2 |
xl | 1280px | xl:max-w-5xl |
<div class="px-hsp-sm sm:px-hsp-md lg:px-hsp-lg xl:px-hsp-xl">
Responsive horizontal padding
</div>Z-index Tier
任意のスタック値ではなく、意味を持つ z-index tier を使ってください。
| トークン | 値 | 使用例 |
|---|---|---|
content | 0 | z-content |
local-1 | 1 | z-local-1 |
local-2 | 2 | z-local-2 |
local-3 | 3 | z-local-3 |
sidebar | 10 | z-sidebar |
toolbar | 20 | z-toolbar |
dropdown | 30 | z-dropdown |
popover | 40 | z-popover |
modal-backdrop | 50 | z-modal-backdrop |
modal | 60 | z-modal |
toast | 70 | z-toast |
tooltip | 80 | z-tooltip |
drag | 90 | z-drag |
カラー
カラーは3層戦略を採用しています。生のパレット値(Tier 1)がセマンティックトークン(Tier 2)に流れ込み、さらにコンポーネントスコープのトークン(Tier 3)に供給されます。各層は上の層のみを参照するため、カラースキームを切り替えるとサイト全体が一括で更新されます。
カラートークンシステム、カラースキーム、カスタマイズの詳細はカラーリファレンスを参照してください。
使用ルール
Tailwindのデフォルトテーマは無効
Tailwindのデフォルトテーマはインポートされていません。プロジェクトトークンは @takazudo/ から来て、その後にプロジェクトの @theme 上書きブロックが適用されます。定義されていないトークンはスタイルなしのマークアップになります。
推奨
<!-- Semantic color tokens -->
<p class="text-fg">Primary text</p>
<div class="bg-surface border border-muted">Panel</div>
<a class="text-accent hover:text-accent-hover">Link</a>
<!-- Spacing tokens -->
<div class="px-hsp-lg py-vsp-md">Proper spacing</div>
<div class="gap-x-hsp-sm gap-y-vsp-md">Grid gaps</div>
<!-- Typography tokens -->
<h2 class="text-title font-semibold leading-tight">Heading</h2>非推奨
<!-- DON'T: Tailwind defaults — not defined and produce nothing -->
<div class="p-4 bg-gray-500 text-sm">Broken</div>
<!-- DON'T: Hardcoded hex — breaks theming -->
<div class="bg-[#1e1e2e] text-[#f8f8f2]">Breaks on theme switch</div>デフォルトトークンは @takazudo/ から提供され、packages/ が唯一の情報源です。scaffold の src/ はそれらのデフォルトをインポートし、プロジェクトの上書きポイントを提供します。
インタラクションのルール
リンク要素にホバー時の下線を使う
遷移する 要素(<a href>、またはリンクとして振る舞う要素)は、ホバー時とキーボードフォーカス時にアンダーラインを表示します。ボタン、トグル、コントロールは対象外で、ボーダー/背景の変化で代替します。
OK(ナビゲーション用のリンク):
<a class="text-accent hover:underline focus-visible:underline">Link</a>
<a class="text-fg hover:text-accent hover:underline focus-visible:underline">Sidebar item</a>NG(focus-visible が欠けている):
<!-- DON'T: mouse users get an underline, keyboard users don't -->
<a class="text-fg hover:underline">Inaccessible to keyboard focus</a>NG(コントロール):
<!-- DON'T: buttons use border/bg hover, not underline -->
<button class="hover:underline">Use hover:bg-accent/10 instead</button>hover:underline focus-visible:underline のペアが正規形です。必ず両方を書き、片方だけにはしないでください。実装例:packages/、src/、packages/。
より深い背景(ライト/ダークのコントラスト、下線だけで足りるか色の変化も必要か)は、ローカルの / スキルを参照してください。light-mode/dark-mode と three-tier トークン戦略のセクションがトレードオフを扱っています。