shadcn/ui
UI、コンポーネント、デザインシステムを構築するためのフレームワークです。コンポーネントはCLIを介してユーザープロジェクトにソースコードとして追加されます。
重要: すべてのCLIコマンドは、プロジェクトのパッケージランナーを使用して実行します:
npx shadcn@latest、pnpm dlx shadcn@latest、またはbunx --bun shadcn@latest— プロジェクトのpackageManagerに基づいて選択します。以下の例ではnpx shadcn@latestを使用していますが、プロジェクトに適した正しいランナーに置き換えてください。
現在のプロジェクトコンテキスト
!`npx shadcn@latest info --json`
上記のJSONには、プロジェクトの設定とインストール済みコンポーネントが含まれています。任意のコンポーネントのドキュメントと使用例のURLを取得するには、npx shadcn@latest docs <コンポーネント>を使用します。
原則
- 既存のコンポーネントを優先する。 カスタム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-*を使用する。size-10であってw-10 h-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
- アイテムは常にそのGroup内に配置する。
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を使用する。 カスタムの空状態マークアップを構築しない。 - トーストはプロジェクトのベースに従う。 Base UIプロジェクトでは
toastコンポーネントのtoastを使用する。RadixおよびReact Ariaプロジェクトではsonnerのtoast()を使用する。 Separatorを使用する。<hr>や<div className="border-t">の代わりに。- ローディングプレースホルダーには
Skeletonを使用する。 カスタムのanimate-pulsedivは使用しない。 Badgeを使用する。 カスタムスタイルのspanの代わりに。
アイコン → icons.md
Button内のアイコンにはdata-iconを使用する。 アイコンにdata-icon="inline-start"またはdata-icon="inline-end"。- コンポーネント内のアイコンにサイジングクラスを付けない。 コンポーネントはCSSでアイコンのサイズを処理します。
size-4やw-4 h-4は不要。 - アイコンは文字列キーではなくオブジェクトとして渡す。
icon={CheckIcon}、文字列参照ではない。
チャットとメッセージング → chat.md
- チャットUIはチャットプリミティブを構成する。 会話には
MessageScroller、行にはMessage、表面にはBubbleを使用する。手作りのバブルdivや生のスクロールコンテナは使用しない。 MessageScrollerがスクロール動作を管理する。 ストリーミング追従、アンカー、最新へジャンプ(MessageScrollerButton)は組み込み。useStickToBottom/ResizeObserverフックを書かない。- 添付ファイルには
Attachment、システムノートと区切りにはMarkerを使用する。ItemカードやSeparator+ ラベルは使用しない。
CLI
- プリセットコードをデコードしたり、プリセットURLを手動で構築したりしない。
npx shadcn@latest preset decode <コード>、preset url <コード>、またはpreset open <コード>を使用する。プロジェクトを認識したプリセット検出にはnpx shadcn@latest preset resolveを使用する。 - プリセットコードはCLIで直接適用する。 既存プロジェクトには
npx shadcn@latest apply <コード>、初期化時にはnpx shadcn@latest init --preset <コード>を使用する。
主要パターン
これらは、正しいshadcn/uiコードを区別する最も一般的なパターンです。エッジケースについては、上記のリンクされたルールファイルを参照してください。
// フォームレイアウト: FieldGroup + Field、div + Labelではない。
<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>
// スペーシング: gap-*、space-y-*ではない。
<div className="flex flex-col gap-4"> // 正しい
<div className="space-y-4"> // 間違い
// 等しい寸法: size-*、w-* h-*ではない。
<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(確認) |
| フィードバック | toast(Base UI)、sonner(Radix/Aria)、Alert、Progress、Skeleton、Spinner |
| コマンドパレット | Dialog内のCommand |
| チャート | Chart(Rechartsをラップ) |
| レイアウト | Card、Separator、Resizable、ScrollArea、Accordion、Collapsible |
| 空の状態 | Empty |
| メニュー | DropdownMenu、ContextMenu、Menubar |
| ツールチップ/情報 | Tooltip、HoverCard、Popover |
| チャット/会話UI | MessageScroller、Message、Bubble、Attachment、Marker |
主要フィールド
注入されたプロジェクトコンテキストには、以下の主要フィールドが含まれています:
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と利用可能なpropsに影響します。iconLibrary→ アイコンのインポートを決定します。lucideの場合はlucide-react、tablerの場合は@tabler/icons-reactなど。lucide-reactを想定しないこと。resolvedPaths→ コンポーネント、ユーティリティ、フックなどの正確なファイルシステム上の出力先。framework→ ルーティングとファイル規約(例: Next.js App Router vs Vite SPA)。packageManager→ shadcn以外の依存関係のインストールに使用(例:pnpm add date-fnsvsnpm install date-fns)。preset→ 現在のプロジェクトの解決済みプリセットコードと値。プリセット情報のみが必要な場合は、npx shadcn@latest preset resolve --jsonを使用する。
完全なフィールドリファレンスは cli.md — info コマンド を参照してください。
コンポーネントのドキュメント、例、使用方法
npx shadcn@latest docs <コンポーネント> を実行すると、コンポーネントのドキュメント、例、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 <コンポーネント>を実行して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、owner/repoなどを指定せずに「ログインブロックを追加」と言った場合)、どのレジストリを使用するか尋ねてください。ユーザーに代わってレジストリをデフォルトにしないでください。 - プリセットの切り替え — 最初にユーザーに尋ねます: 上書き(overwrite)、部分適用(partial)、マージ(merge)、スキップ(skip)?
- 現在のプリセットを確認:
npx shadcn@latest preset resolve。構造化された値が必要な場合は--jsonを使用します。 - 新しいプリセットを確認:
npx shadcn@latest preset decode <コード>。プリセットビルダーを共有または開くにはpreset url <コード>またはpreset open <コード>を使用します。 - 上書き:
npx shadcn@latest apply <コード>。検出されたコンポーネント、フォント、CSS変数を上書きします。 - 部分適用:
npx shadcn@latest apply <コード> --only theme,font。UIコンポーネントを再インストールせずに、選択したプリセット部分のみを更新します。サポートされている値はthemeとfontです。カンマ区切りの組み合わせが可能です。iconは意図的にサポートされていません。アイコンの変更には完全なコンポーネントの再インストールが必要になる場合があるためです。
- 現在のプリセットを確認:
- コンポーネントの更新 —
npx shadcn@latest add <コンポーネント名> --dry-run --diffを使用して、インストール済みコンポーネントへの保留中の変更を確認します。コンポーネントを更新するときは常にこれを行い、CLIが何を変更しようとしているかを把握してから適用してください。
コンポーネントの更新
npx shadcn@latest add <component> --dry-run --diff を使用して、インストール済みコンポーネントに対する保留中の変更を確認します。コンポーネントを更新する際は常にこれを行い、CLIが何を変更しようとしているかを把握してから適用してください。
npx shadcn@latest add button --dry-run --diff
これにより、アップストリームの変更とローカルファイルの差分が表示されます。変更に問題がなければ、--dry-runなしでコマンドを実行して適用します。
トラブルシューティング
一般的な問題
- コンポーネントが見つからない —
npx shadcn@latest search <用語>で利用可能なコンポーネントとレジストリを検索します。 - プリセットの問題 —
npx shadcn@latest preset resolveで現在のプリセットを確認します。 - 依存関係の問題 — プロジェクトのパッケージマネージャーを使用して依存関係がインストールされていることを確認します。
- インポートパス —
resolvedPathsを使用して正しいインポートパスを確認します。 - ビルドエラー — コンポーネントが正しく構成されているか、
isRSCに基づいて適切なディレクティブ("use client")があるかを確認します。
サポート
- ドキュメント:
npx shadcn@latest docs <コンポーネント>で最新のドキュメントURLを取得します。 - レジストリの閲覧:
npx shadcn@latest viewでインストールしていないアイテムを探索します。 - 変更のプレビュー:
npx shadcn@latest add --diffでインストール済みコンポーネントへの変更をプレビューします。