shadcn/ui
UI、コンポーネント、デザインシステムを構築するためのフレームワーク。コンポーネントはCLIを介してソースコードとしてユーザーのプロジェクトに追加されます。
重要: すべてのCLIコマンドは、プロジェクトのパッケージランナーを使用して実行してください:プロジェクトの
packageManagerに応じてnpx shadcn@latest、pnpm dlx shadcn@latest、またはbunx --bun shadcn@latestを使用します。以下の例ではnpx shadcn@latestを使用していますが、プロジェクトに合ったランナーに置き換えてください。
現在のプロジェクトコンテキスト
!`npx shadcn@latest info --json`
上記のJSONには、プロジェクトの設定とインストール済みコンポーネントが含まれています。任意のコンポーネントのドキュメントと使用例のURLを取得するには、npx shadcn@latest docs <component> を使用します。
原則
- 既存のコンポーネントを優先して使用する。 カスタムUIを作成する前に
npx shadcn@latest searchを使用してレジストリを確認してください。コミュニティレジストリも確認してください。 - 組み合わせる、再発明しない。 設定ページ = Tabs + Card + フォームコントロール。ダッシュボード = Sidebar + Card + Chart + Table。
- カスタムスタイルの前に組み込みのバリアントを使用する。
variant="outline"、size="sm"など。 - セマンティックカラーを使用する。
bg-primary、text-muted-foreground—bg-blue-500のような生の値は絶対に使用しないこと。
重要なルール
これらのルールは常に適用されます。各ルールは、誤ったコードと正しいコードのペアが記載されたファイルにリンクしています。
スタイリング & Tailwind → styling.md
classNameはレイアウトに使用し、スタイリングには使用しない。 コンポーネントの色やタイポグラフィをオーバーライドしないでください。space-x-*やspace-y-*は使用しない。flexとgap-*を使用してください。縦方向のスタックにはflex flex-col gap-*を使用します。- 幅と高さが等しい場合は
size-*を使用する。w-10 h-10ではなくsize-10を使用します。 truncateのショートハンドを使用する。overflow-hidden text-ellipsis whitespace-nowrapではありません。- 手動で
dark:カラーをオーバーライドしない。 セマンティックトークン(bg-background、text-muted-foreground)を使用します。 - 条件付きクラスには
cn()を使用する。 手動でテンプレートリテラルの三項演算子を記述しないでください。 - オーバーレイコンポーネントに手動で
z-indexを設定しない。 Dialog、Sheet、Popover などは独自のスタッキングを処理します。
フォーム & 入力 → forms.md
- フォームには
FieldGroup+Fieldを使用する。 フォームレイアウトに生のdivとspace-y-*またはgrid gap-*を使用しないでください。 InputGroupにはInputGroupInput/InputGroupTextareaを使用する。InputGroup内で生のInput/Textareaを使用しないでください。- 入力内のボタンには
InputGroup+InputGroupAddonを使用する。 - オプションセット(2~7の選択肢)には
ToggleGroupを使用する。 手動のアクティブ状態を持つButtonをループしないでください。 - 関連するチェックボックス/ラジオボタンをグループ化するには
FieldSet+FieldLegendを使用する。 見出し付きのdivを使用しないでください。 - フィールドのバリデーションには
data-invalid+aria-invalidを使用する。Fieldにdata-invalid、コントロールにaria-invalidを設定します。無効の場合は、Fieldにdata-disabled、コントロールにdisabledを設定します。
コンポーネント構造 → composition.md
- アイテムは常にそのグループ内に配置する。
SelectItem→SelectGroup、DropdownMenuItem→DropdownMenuGroup、CommandItem→CommandGroup。 - カスタムトリガーには
asChild(radix) またはrender(base) を使用する。npx shadcn@latest infoからbaseフィールドを確認してください。→ base-vs-radix.md - Dialog、Sheet、Drawer には常に Title が必要。 アクセシビリティのために
DialogTitle、SheetTitle、DrawerTitleが必要です。視覚的に非表示にする場合はclassName="sr-only"を使用します。 - 完全な Card 構成を使用する。
CardHeader/CardTitle/CardDescription/CardContent/CardFooterを使用します。すべてをCardContentに詰め込まないでください。 - Button に
isPending/isLoadingはありません。Spinner+data-icon+disabledで構成します。 TabsTriggerはTabsList内になければなりません。 トリガーをTabsに直接レンダリングしないでください。Avatarには常にAvatarFallbackが必要。 画像の読み込みに失敗した場合に備えます。
カスタムマークアップではなくコンポーネントを使用 → composition.md
- カスタムマークアップの前に既存のコンポーネントを使用する。 スタイル付き
divを記述する前に、コンポーネントが存在するか確認してください。 - コールアウトには
Alertを使用する。 カスタムのスタイル付き div を構築しないでください。 - 空の状態には
Emptyを使用する。 カスタムの空の状態マークアップを構築しないでください。 - Toast は
sonner経由で行う。sonnerのtoast()を使用します。 <hr>や<div className="border-t">の代わりにSeparatorを使用する。- ローディングプレースホルダーには
Skeletonを使用する。 カスタムのanimate-pulsediv は使用しないでください。 - カスタムのスタイル付き span の代わりに
Badgeを使用する。
アイコン → icons.md
Button内のアイコンにはdata-iconを使用する。 アイコンにdata-icon="inline-start"またはdata-icon="inline-end"を設定します。- コンポーネント内のアイコンにサイズクラスを設定しない。 コンポーネントはCSSでアイコンサイズを処理します。
size-4やw-4 h-4は使用しないでください。 - アイコンは文字列キーではなくオブジェクトとして渡す。 文字列ルックアップではなく
icon={CheckIcon}のように渡します。
CLI
- プリセットコードを手動でデコードしたりフェッチしたりしない。 それらを直接
npx shadcn@latest init --preset <code>に渡します。
主要パターン
これらは、正しい shadcn/ui コードを区別する最も一般的なパターンです。エッジケースについては、上記のリンクされたルールファイルを参照してください。
// フォームレイアウト: div + Label ではなく FieldGroup + Field。
<FieldGroup>
<Field>
<FieldLabel htmlFor="email">メールアドレス</FieldLabel>
<Input id="email" />
</Field>
</FieldGroup>
// バリデーション: Field に data-invalid、コントロールに aria-invalid。
<Field data-invalid>
<FieldLabel>メールアドレス</FieldLabel>
<Input aria-invalid />
<FieldDescription>無効なメールアドレスです。</FieldDescription>
</Field>
// ボタン内のアイコン: data-icon、サイズクラスは不要。
<Button>
<SearchIcon data-icon="inline-start" />
検索
</Button>
// スペーシング: space-y-* ではなく gap-*。
<div className="flex flex-col gap-4"> // 正しい
<div className="space-y-4"> // 間違い
// 等しい寸法: w-* h-* ではなく size-*。
<Avatar className="size-10"> // 正しい
<Avatar className="w-10 h-10"> // 間違い
// ステータスカラー: 生の色ではなく Badge バリアントまたはセマンティックトークン。
<Badge variant="secondary">+20.1%</Badge> // 正しい
<span className="text-emerald-600">+20.1%</span> // 間違い
コンポーネント選択
| ニーズ | 使用方法 |
|---|---|
| ボタン/アクション | 適切なバリアントの Button |
| フォーム入力 | Input、Select、Combobox、Switch、Checkbox、RadioGroup、Textarea、InputOTP、Slider |
| 2~5個のオプションの切り替え | ToggleGroup + ToggleGroupItem |
| データ表示 | Table、Card、Badge、Avatar |
| ナビゲーション | Sidebar、NavigationMenu、Breadcrumb、Tabs、Pagination |
| オーバーレイ | Dialog(モーダル)、Sheet(サイドパネル)、Drawer(ボトムシート)、AlertDialog(確認) |
| フィードバック | sonner(トースト)、Alert、Progress、Skeleton、Spinner |
| コマンドパレット | Dialog 内の Command |
| チャート | Chart(Recharts をラップ) |
| レイアウト | Card、Separator、Resizable、ScrollArea、Accordion、Collapsible |
| 空の状態 | Empty |
| メニュー | DropdownMenu、ContextMenu、Menubar |
| ツールチップ/情報 | Tooltip、HoverCard、Popover |
主要フィールド
注入されたプロジェクトコンテキストには、次の主要フィールドが含まれています。
aliases→ インポートに実際のエイリアスプレフィックス(例:@/、~/)を使用し、ハードコードしないでください。isRSC→trueの場合、useState、useEffect、イベントハンドラ、またはブラウザAPIを使用するコンポーネントには、ファイルの先頭に"use client"が必要です。ディレクティブについてアドバイスする際は、常にこのフィールドを参照してください。tailwindVersion→"v4"は@theme inlineブロックを使用します。"v3"はtailwind.config.jsを使用します。tailwindCssFile→ カスタムCSS変数が定義されているグローバルCSSファイル。常にこのファイルを編集し、新しいファイルを作成しないでください。style→ コンポーネントのビジュアル処理(例:nova、vega)。base→ プリミティブライブラリ(radixまたはbase)。コンポーネントAPIと使用可能なプロパティに影響します。iconLibrary→ アイコンのインポート元を決定します。lucideの場合はlucide-react、tablerの場合は@tabler/icons-reactなど。決してlucide-reactを想定しないでください。resolvedPaths→ コンポーネント、ユーティリティ、フックなどの正確なファイルシステムの保存先。framework→ ルーティングとファイルの規則(例:Next.js App Router と Vite SPA)。packageManager→ shadcn 以外の依存関係のインストールにこれを使用します(例:pnpm add date-fnsとnpm install date-fns)。
完全なフィールドリファレンスについては、cli.md — info コマンド を参照してください。
コンポーネントドキュメント、例、使用法
npx shadcn@latest docs <component> を実行して、コンポーネントのドキュメント、例、APIリファレンスのURLを取得します。これらのURLをフェッチして実際のコンテンツを取得します。
npx shadcn@latest docs button dialog select
コンポーネントを作成、修正、デバッグ、または使用するときは、常に最初に npx shadcn@latest docs を実行し、URLをフェッチしてください。 これにより、推測ではなく正しいAPIと使用パターンで作業できるようになります。
ワークフロー
- プロジェクトコンテキストを取得する — すでに上で注入されています。必要に応じて
npx shadcn@latest infoを再度実行してリフレッシュしてください。 - 最初にインストール済みコンポーネントを確認する —
addを実行する前に、常にプロジェクトコンテキストのcomponentsリストを確認するか、resolvedPaths.uiディレクトリをリストアップしてください。追加されていないコンポーネントをインポートしないでください。また、すでにインストールされているものを再追加しないでください。 - コンポーネントを検索する —
npx shadcn@latest search。 - ドキュメントと例を取得する —
npx shadcn@latest docs <component>を実行してURLを取得し、それらをフェッチします。インストールしていないレジストリアイテムを参照するにはnpx shadcn@latest viewを使用します。インストール済みコンポーネントへの変更をプレビューするにはnpx shadcn@latest add --diffを使用します。 - インストールまたは更新する —
npx shadcn@latest add。既存のコンポーネントを更新する場合は、最初に--dry-runと--diffを使用して変更をプレビューしてください(下記の「コンポーネントの更新」を参照)。 - サードパーティコンポーネントのインポートを修正する — コミュニティレジストリ(例:
@bundui、@magicui)からコンポーネントを追加した後、追加された UI 以外のファイルに@/components/ui/...のようなハードコードされたインポートパスがないか確認します。これらはプロジェクトの実際のエイリアスと一致しません。npx shadcn@latest infoを使用して正しいuiエイリアス(例:@workspace/ui/components)を取得し、それに応じてインポートを書き換えてください。CLI は自身の UI ファイルのインポートを書き換えますが、サードパーティのレジストリコンポーネントはプロジェクトと一致しないデフォルトのパスを使用する場合があります。 - 追加されたコンポーネントを確認する — 任意のレジストリからコンポーネントまたはブロックを追加した後、常に追加されたファイルを読み、正しいことを確認してください。 欠落しているサブコンポーネント(例:
SelectGroupなしのSelectItem)、欠落しているインポート、誤った構成、または重要なルールの違反がないか確認します。また、アイコンのインポートをプロジェクトコンテキストのiconLibraryに置き換えます(例:レジストリアイテムがlucide-reactを使用しているがプロジェクトがhugeiconsを使用している場合、インポートとアイコン名を適宜交換します)。先に進む前にすべての問題を修正してください。 - レジストリは明示的に指定する必要がある — ユーザーがブロックまたはコンポーネントの追加を依頼した場合、レジストリを推測しないでください。 レジストリが指定されていない場合(例:ユーザーが
@shadcn、@tailarkなどを指定せずに「ログインブロックを追加して」と言った場合)、どのレジストリを使用するか尋ねてください。ユーザーに代わってレジストリをデフォルトにしないでください。 - プリセットの切り替え — 最初にユーザーに尋ねます:再インストール、マージ、またはスキップ?
- 再インストール:
npx shadcn@latest init --preset <code> --force --reinstall。すべてのコンポーネントを上書きします。 - マージ:
npx shadcn@latest init --preset <code> --force --no-reinstall、その後npx shadcn@latest infoを実行してインストール済みコンポーネントをリストアップし、各インストール済みコンポーネントに対して--dry-runと--diffを使用して個別にスマートマージします。 - スキップ:
npx shadcn@latest init --preset <code> --force --no-reinstall。設定とCSSのみを更新し、コンポーネントはそのままにします。 - 重要: 常にユーザーのプロジェクトディレクトリ内でプリセットコマンドを実行してください。CLI は
components.jsonから現在のベース(baseとradix)を自動的に保持します。スクラッチ/テンプディレクトリを使用する必要がある場合(例:--dry-run比較の場合)、--base <現在のベース>を明示的に渡します。プリセットコードはベースをエンコードしません。
- 再インストール:
コンポーネントの更新
ユーザーがローカルの変更を保持しながらアップストリームからコンポーネントを更新するように要求した場合は、--dry-run と --diff を使用してインテリジェントにマージします。GitHubから生のファイルを手動でフェッチしないでください。常にCLIを使用してください。
npx shadcn@latest add <component> --dry-runを実行して、影響を受けるすべてのファイルを確認します。- 各ファイルについて、
npx shadcn@latest add <component> --diff <file>を実行して、アップストリームとローカルで何が変更されたかを確認します。 - diff に基づいてファイルごとに決定します。
- ローカルに変更がない → 上書きしても安全。
- ローカルに変更がある → ローカルファイルを読み、diff を分析し、ローカルの変更を保持しながらアップストリームの更新を適用します。
- ユーザーが「すべて更新する」と言った場合 →
--overwriteを使用しますが、最初に確認します。
- ユーザーの明示的な承認なしに
--overwriteを使用しないでください。
クイックリファレンス
# 新しいプロジェクトを作成する。
npx shadcn@latest init --name my-app --preset base-nova
npx shadcn@latest init --name my-app --preset a2r6bw --template vite
# モノレポプロジェクトを作成する。
npx shadcn@latest init --name my-app --preset base-nova --monorepo
npx shadcn@latest init --name my-app --preset base-
…
[翻訳のために切り詰められました]