shadcn-svelte は何をしますか?
Svelte 向け UI、コンポーネント、デザインシステムを構築するためのフレームワークです。コンポーネントは CLI を介してユーザーのプロジェクトにソースコードとして追加されます。
重要: すべての CLI コマンドはプロジェクトのパッケージランナーを使用して実行してください:
npx shadcn-svelte@latest、pnpm dlx shadcn-svelte@latest、またはbunx --bun shadcn-svelte@latest— プロジェクトのパッケージマネージャに応じて適切なものを使用します。以下の例ではnpx shadcn-svelte@latestを使用していますが、プロジェクトに合わせて正しいランナーに置き換えてください。
現在のプロジェクトコンテキスト
プロジェクトルートにある components.json を読み取り、ライブファイルレイアウトが必要な場合は、aliases.ui パスで指定されたディレクトリをリスト表示してください(CLI と同じルールで解決します)。
インポート(Svelte)
各コンポーネントは独自のフォルダに index.ts バレルファイルとともに配置されています。インストールドキュメント に従ってください:
- 複数パーツからなるコンポーネント(dialog、select、card、field、tabs など):
import * as Dialog from "$lib/components/ui/dialog"としてインポートし、Dialog.Content、Dialog.Title、Card.Root、Card.Headerなど、バレルがエクスポートするもの(短い名前やRoot as …エイリアス)を使用します。 - 単一コンポーネントのバレル(フォルダ内に実質的に1つのコンポーネントしかない場合):名前付きインポート —
import { Button } from "$lib/components/ui/button"と<Button>を使用します。import * as Button+Button.Rootは使わないでください。{ Input }、{ Badge }、{ Spinner }、{ Checkbox }、{ Separator }、{ Skeleton }なども同様です。
import * as Dialog from "$lib/components/ui/dialog";
import { Button } from "$lib/components/ui/button";
import { Separator } from "$lib/components/ui/separator";
components.json の実際のエイリアス(多くの場合 $lib/components/ui/...)を使用し、ハードコードされたパスは使わないでください。
原則
- 既存のコンポーネントを優先して使用する。 引数なしで
npx shadcn-svelte@latest addを実行して利用可能なコンポーネントを参照するか、カスタム UI を書く前に Components を確認してください。 - 組み合わせて使用し、再発明しない。 設定ページ = Tabs + Card + フォームコントロール。ダッシュボード = Sidebar + Card + Chart + Table。
- カスタムスタイルの前に組み込みバリアントを使用する。
variant="outline"、size="sm"など。 - セマンティックカラーを使用する。
bg-primary、text-muted-foreground—bg-blue-500のような生の値は絶対に使わないでください。
重要なルール
これらのルールは常に適用されます。各ルールは、誤ったコード/正しいコードのペアが記載されたファイルにリンクしています。
スタイリングと Tailwind → styling.md
- レイアウトには
classを使用し、スタイリングには使わない。 コンポーネントの色やタイポグラフィを上書きしないでください。 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
- フォームでは
Field.FieldGroup+Field.Fieldを使用する。 フォームレイアウトに生のdivとspace-y-*やgrid gap-*を使用しないでください。 InputGroupではInputGroup.Input/InputGroup.Textareaを使用する。InputGroup.Root内で生のInput/Textareaを使用しないでください。- 入力内のボタンには
InputGroup.Root+InputGroup.Addonを使用する。 - 選択肢セット(2~7個の選択肢)には
ToggleGroupを使用する。 手動でアクティブ状態を管理するButtonのループを使わないでください。 - 関連するチェックボックス/ラジオをグループ化するには
Field.FieldSet+Field.FieldLegendを使用する。 見出し付きのdivを使用しないでください。 - フィールドのバリデーションには
data-invalid+aria-invalidを使用する。Fieldにはdata-invalid、コントロールにはaria-invalidを設定します。無効の場合:Fieldにはdata-disabled、コントロールにはdisabledを設定します。
コンポーネント構成 → composition.md
- アイテムは常にそのグループ内に配置する。
Select.Item→Select.Group。DropdownMenu.Item→DropdownMenu.Group。Command.Item→Command.Group。 - カスタムトリガー。 コントロールを
Dialog.Trigger/AlertDialog.Triggerでラップするか、ルートでbind:openを使用して開閉状態を制御します — コンポーネントのドキュメントを参照してください。 - Dialog、Sheet、Drawer には常に Title が必要。
Dialog.Title、Sheet.Title、Drawer.Titleはアクセシビリティのために必須です。視覚的に非表示にする場合はclass="sr-only"を使用します。 - 完全な Card 構成を使用する。
Card.Header/Card.Title/Card.Description/Card.Content/Card.Footer。すべてをCard.Contentにまとめないでください。 - Button に
isPending/isLoadingはありません。Button内でSpinnerとdisabledを組み合わせて使用します。Spinnerにdata-icon="inline-start"/inline-endを使用して正しい間隔を確保します(import { Button }、import { Spinner })。 Tabs.TriggerはTabs.List内に配置する必要がある。Tabs内にトリガーを直接レンダリングしないでください。Avatarには常にAvatar.Fallbackが必要。 画像の読み込みに失敗した場合に備えます。
コンポーネントを使い、カスタムマークアップを使わない → composition.md
- カスタムマークアップの前に既存のコンポーネントを使用する。 スタイル付きの
divを書く前に、コンポーネントが存在するか確認してください。 - コールアウトには
Alertを使用する。 カスタムのスタイル付き div を構築しないでください。 - 空の状態には
Emptyを使用する。 カスタムの空状態マークアップを構築しないでください。 - トーストは
svelte-sonner経由で。 UI フォルダの Sonner コンポーネントとともに、svelte-sonnerのtoast()を使用します。 Separatorを使用する。<hr>や境界線のみのクラスを持つdivの代わりに使用します。- ローディングプレースホルダには
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は使わないでください。 - アイコンはコンポーネントとして渡す。 設定された
iconLibrary(例:@lucide/svelte)からインポートし、文字列キーでは渡さないでください。
CLI
- プリセット — shadcn-svelte.com のデザインシステムビルダーからエンコードされた文字列をコピーし、
npx shadcn-svelte@latest init --preset <code>に渡します。
主要パターン
以下は、正しい shadcn-svelte コードを区別する最も一般的なパターンです。エッジケースについては、上記のリンク先ルールファイルを参照してください。
<script lang="ts">
import * as Field from "$lib/components/ui/field";
import { Input } from "$lib/components/ui/input";
import { Button } from "$lib/components/ui/button";
import SearchIcon from "@lucide/svelte/icons/search";
import { Badge } from "$lib/components/ui/badge";
import * as Avatar from "$lib/components/ui/avatar";
</script>
<!-- フォームレイアウト: Field.FieldGroup + Field.Field、 div + Label ではありません。 -->
<Field.FieldGroup>
<Field.Field>
<Field.FieldLabel for="email">メールアドレス</Field.FieldLabel>
<Input id="email" />
</Field.Field>
</Field.FieldGroup>
<!-- バリデーション: Field に data-invalid、コントロールに aria-invalid -->
<Field.Field data-invalid>
<Field.FieldLabel for="email">メールアドレス</Field.FieldLabel>
<Input id="email" aria-invalid />
<Field.FieldDescription>無効なメールアドレスです。</Field.FieldDescription>
</Field.Field>
<!-- ボタン内のアイコン: data-icon、サイズクラスは不要 -->
<Button>
<SearchIcon data-icon="inline-start" />
検索
</Button>
<!-- 間隔: gap-*、space-y-* ではありません。 -->
<div class="flex flex-col gap-4"></div>
<!-- 等しい寸法: size-*、w-* h-* ではありません。 -->
<Avatar.Root class="size-10">
<Avatar.Image src="/u.png" alt="ユーザー" />
<Avatar.Fallback>U</Avatar.Fallback>
</Avatar.Root>
<!-- 状態色: Badge バリアントまたはセマンティックトークン、生の色ではありません。 -->
<Badge variant="secondary">+20.1%</Badge>
コンポーネント選択
| ニーズ | 使用するコンポーネント |
|---|---|
| ボタン/アクション | 適切な variant の Button(import { Button }) |
| フォーム入力 | Input、Select、Combobox、Switch、Checkbox、RadioGroup、Textarea、InputOTP、Slider |
| 2~5個の選択肢の切り替え | ToggleGroup.Root + ToggleGroup.Item |
| データ表示 | Table、Card、Badge、Avatar |
| ナビゲーション | Sidebar、NavigationMenu、Breadcrumb、Tabs、Pagination |
| オーバーレイ | Dialog(モーダル)、Sheet(サイドパネル)、Drawer(ボトムシート)、AlertDialog(確認) |
| フィードバック | svelte-sonner(トースト)、Alert、Progress、Skeleton、Spinner |
| コマンドパレット | Dialog 内の Command |
| チャート | Chart(LayerChart) |
| レイアウト | Card、Separator、Resizable、ScrollArea、Accordion、Collapsible |
| 空の状態 | Empty |
| メニュー | DropdownMenu、ContextMenu、Menubar |
| ツールチップ/情報 | Tooltip、HoverCard、Popover |
主要フィールド
components.json とファイルシステムを使用します。別個の info コマンドは使用しません:
aliases→ 設定からの実際のエイリアスプレフィックス(例:$lib/)を使用します。無関係なプロジェクトをハードコードしないでください。tailwind.css→ テーマ変数が存在するグローバル CSS ファイル。テーマの調整にはこのファイルを編集します。ユーザーが既に使用していない限り、2つ目のグローバルファイルを追加しないでください。style→ 視覚的な処理(例:nova、vegaなど)とレジストリスタイルパス。iconLibrary→ アイコンパッケージを決定します(@lucide/svelte、@tabler/icons-svelteなど)。@lucide/svelteを想定しないでください。registry→ CLI がコンポーネントを取得する場所。デフォルトはshadcn-svelte.comの公式レジストリ。resolvedPaths(概念)→ CLI がaliasesを絶対パスに解決します。インストール済みコンポーネントを確認するには、aliases.uiをディスク上でリスト表示します。
コマンドとフラグについては cli.md を参照してください。
コンポーネントのドキュメント、例、使い方
ドキュメントと例については https://shadcn-svelte.com/docs/components/<name>.md を開いてください。コンポーネントを作成、修正、デバッグ、または使用する際は、最初に公式ページを読んで、ドキュメント化された API に従ってください。
ワークフロー
- プロジェクトコンテキストを取得 —
components.jsonを読み取り、必要に応じて UI コンポーネントディレクトリをリスト表示します。 - 最初にインストール済みコンポーネントを確認 —
addを実行する前に、解決されたuiパス下のファイルをリスト表示します。追加されていないコンポーネントをインポートせず、更新しない限り既存のものを再追加しないでください。 - コンポーネントを発見 — 引数なしの
npx shadcn-svelte@latest add(インタラクティブリスト)、またはドキュメントサイト。 - インストールまたは更新 —
npx shadcn-svelte@latest add <name>またはレジストリ URL。レジストリから既存のファイルを更新するには、npx shadcn-svelte@latest updateを使用します(cli.md 参照)。 - サードパーティ/URL で追加されたアイテムのインポートを修正 — カスタムレジストリ URL から追加した後、プロジェクトの
aliasesと一致しないハードコードされたパスがないか確認します。components.jsonのプロジェクトのui/libエイリアスを使用するようにインポートを書き換えます。 - 追加したコンポーネントをレビュー — 追加後、追加されたファイルを読み、構成(グループ、タイトル、バリデーション属性)を検証します。アイコンのインポートを
iconLibraryに合わせます。 - リモートレジストリアイテム — URL による追加は明示的です。ユーザーが未知のソースからのコンポーネントを希望する場合、
addを実行する前にレジストリ URL またはアイテムを確認します。
DESIGN.md からのデザインシステム
ユーザーが DESIGN.md(またはブランド仕様)からデザインシステムを要求した場合、プリセットの有無にかかわらず、design-system.md に従って最初から最後まで実行します:
- 新しいアプリの場合、
npx sv create <app>で SvelteKit をスキャフォールドし(または要求に応じて Svelte + Vite)、npx shadcn-svelte@latest init --preset <code>で初期化します。コードがない場合は、DESIGN.md に合ったスタイルを選び、その名前を渡します(例:init --preset luma)。React のプリセットコードとスキャフォールディングフラグは適用されません。既存のアプリでは、ローカルのカスタマイズを保持します。 - 新しいアプリでは
add --all --yesですべてのコンポーネントをインストールします。既存のアプリでは不足しているコンポーネントのみを追加します。 - 編集前に DESIGN.md のフロントマター、Do's and Don'ts、既知のギャップを読みます。
- そのトークンを
components.jsonのtailwind.cssの変数にマッピングします。半径スケール、シャドウ、フォント、type-*ユーティリティを固定します。 - インストール済みの
tailwind-variantsバリアントと関連スタイル CSS を再スタイリングします。コントロールの高さを一緒に変更します。 - design-system-page.md に従ってページを構築します:コントラストチェックされたカラーロール、タイプ見本、固定状態行列、エッジケース、Do/Don't ペア、レシピ。
scripts/showcase-coverage.mjsでインポートを確認し、すべてのコンポーネントがレンダリングされることを確認します。 - ブラウザで確認:
svelte-check、SSR を含むプロダクションビルド、コンソールエラーなし、上部に読み込まれる、横方向オーバーフローなし、ダークモード。
コンポーネントの更新
update コマンドを使用して、プロジェクト内のコンポーネントの最新レジストリバージョンを取得します。update 後は git diff で変更をレビューします。
- ローカルの作業をコミットまたはスタッシュします。
npx shadcn-svelte@latest update [component]または--allを実行します。- ファイルをカスタマイズしていた場合、マージ競合を解決します。
- ユーザーの明示的な承認なしに
addで--overwriteを使用しないでください。 意図的な編集が破壊される可能性があります。
クイックリファレンス
# yo プロジェクトで shadcn-svelte を初期化
…
[翻訳のために一部省略]