shadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表
shadcn/ui は豊富なコンポーネントを提供していますが、「この機能を実装したいけど、どのコンポーネントを使えばいいんだろう?」と迷った経験はありませんか。
60 種類以上のコンポーネントから最適なものを選ぶのは、初心者にとってもベテラン開発者にとっても時間のかかる作業です。本記事では、用途別に shadcn/ui コンポーネントを即座に見つけられる選定マップを提供します。
早見表を活用すれば、迷う時間を削減し、開発スピードを大幅に向上させられるでしょう。
コンポーネント早見表
データ表示系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | 表形式データ表示 | Table | Data Table | 商品一覧、ユーザーリスト |
| 2 | カード型表示 | Card | - | ダッシュボード、記事一覧 |
| 3 | 統計・数値表示 | Card + Badge | - | KPI、メトリクス表示 |
| 4 | プロフィール表示 | Avatar + Card | - | ユーザー情報、アカウント |
| 5 | 進捗状況表示 | Progress | - | アップロード、処理進行度 |
| 6 | ステータス表示 | Badge | - | タグ、状態ラベル |
| 7 | 階層データ表示 | Accordion | Collapsible | FAQ、ネストメニュー |
| 8 | タブ切り替え表示 | Tabs | - | 設定画面、複数ビュー |
フォーム・入力系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | テキスト入力 | Input | Textarea | 名前、メール入力 |
| 2 | 複数行テキスト | Textarea | - | コメント、説明文入力 |
| 3 | 選択肢(少数) | Radio Group | Select | 性別、サイズ選択 |
| 4 | 選択肢(多数) | Select | Combobox | 国選択、カテゴリ選択 |
| 5 | 検索可能選択 | Combobox | Command | タグ選択、ユーザー検索 |
| 6 | 複数選択 | Checkbox | - | 利用規約、オプション選択 |
| 7 | ON/OFF 切替 | Switch | Checkbox | 通知設定、機能有効化 |
| 8 | 数値範囲選択 | Slider | Input(number) | 価格帯、音量調整 |
| 9 | 日付選択 | Calendar + Popover | Input(date) | 予約日、締切日設定 |
| 10 | ファイル選択 | Input(file) + Label | - | 画像アップロード |
ナビゲーション系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | メインメニュー | Navigation Menu | Menubar | ヘッダーナビゲーション |
| 2 | サイドメニュー | Sheet + Navigation | Accordion | 管理画面サイドバー |
| 3 | パンくずリスト | Breadcrumb | - | ページ階層表示 |
| 4 | ページネーション | Pagination | - | 一覧ページ |
| 5 | コマンド検索 | Command | Combobox | ショートカットメニュー |
| 6 | コンテキストメニュー | Context Menu | Dropdown Menu | 右クリックメニュー |
| 7 | ドロップダウン | Dropdown Menu | Popover | アクションメニュー |
フィードバック系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | 成功メッセージ | Toast | Alert | 保存完了通知 |
| 2 | エラー表示 | Alert | Toast | フォームエラー |
| 3 | 確認ダイアログ | Alert Dialog | Dialog | 削除確認 |
| 4 | 情報ダイアログ | Dialog | Sheet | 詳細情報表示 |
| 5 | ローディング | Skeleton | Spinner(custom) | データ読込中 |
| 6 | ツールチップ | Tooltip | Popover | 補足説明 |
| 7 | ホバー情報 | Hover Card | Tooltip | プレビュー表示 |
レイアウト系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | セクション区切り | Separator | - | コンテンツ区切り |
| 2 | 折りたたみ | Collapsible | Accordion | オプション表示・非表示 |
| 3 | スクロール領域 | Scroll Area | div(overflow) | 長いリスト |
| 4 | アスペクト比固定 | Aspect Ratio | div(padding-trick) | 動画埋め込み |
| 5 | リサイズ可能 | Resizable | - | 分割パネル |
オーバーレイ系コンポーネント
| # | 用途 | 推奨コンポーネント | 代替候補 | 使用場面 |
|---|---|---|---|---|
| 1 | モーダル | Dialog | Alert Dialog | フォーム入力画面 |
| 2 | サイドパネル | Sheet | Dialog | フィルター設定 |
| 3 | ポップアップ | Popover | Tooltip | 追加情報表示 |
| 4 | ドロワー(モバイル) | Sheet | Dialog | モバイルメニュー |
背景
shadcn/ui の特徴と人気の理由
shadcn/ui は、2023 年にリリースされて以来、React 開発者の間で急速に人気を集めている UI コンポーネントライブラリです。従来のコンポーネントライブラリとは異なり、npm パッケージとしてインストールするのではなく、コンポーネントのソースコードを直接プロジェクトにコピーする方式を採用しています。
この独特なアプローチにより、開発者は完全なカスタマイズ性を手に入れられるのです。
豊富なコンポーネントラインナップ
shadcn/ui は現在 60 種類以上のコンポーネントを提供しており、その数は継続的に増加しています。各コンポーネントは Radix UI をベースに構築され、アクセシビリティとユーザビリティが徹底的に考慮されているのが特徴でしょう。
以下の図は、shadcn/ui のコンポーネントがどのように分類されているかを示しています。
mermaidflowchart TD
root["shadcn/ui<br/>コンポーネント"] --> display["データ表示系"]
root --> form["フォーム・入力系"]
root --> nav["ナビゲーション系"]
root --> feedback["フィードバック系"]
root --> layout["レイアウト系"]
root --> overlay["オーバーレイ系"]
display --> table["Table/Card/Badge"]
form --> input["Input/Select/Checkbox"]
nav --> menu["Navigation Menu/Command"]
feedback --> alert["Alert/Toast/Dialog"]
layout --> separator["Separator/Collapsible"]
overlay --> modal["Dialog/Sheet/Popover"]
この図から分かるように、shadcn/ui のコンポーネントは大きく 6 つのカテゴリに分類できます。
TypeScript と Tailwind CSS との統合
shadcn/ui のすべてのコンポーネントは TypeScript で記述され、Tailwind CSS によるスタイリングが施されています。この組み合わせにより、型安全性を保ちながら、柔軟なデザインカスタマイズが可能になるのです。
Next.js、Remix、Vite など、主要な React フレームワークとの互換性も高く、導入障壁が低いことも人気の理由と言えますね。
課題
コンポーネント選定の難しさ
shadcn/ui の豊富なコンポーネントラインナップは大きな利点ですが、同時に「どのコンポーネントを使えばいいのか」という新たな課題を生み出しています。
特に以下のような場面で、開発者は選定に迷いがちです。
類似コンポーネントの存在による混乱
例えば、「ユーザーに選択肢を提示したい」という要件に対して、以下の複数のコンポーネントが候補として挙げられます:
- Select:ドロップダウン形式の選択
- Combobox:検索機能付き選択
- Radio Group:ラジオボタン形式の選択
- Checkbox:複数選択可能なチェックボックス
これらの違いを正確に理解していないと、要件に合わないコンポーネントを選んでしまい、後から作り直す羽目になるでしょう。
ドキュメント探索の時間コスト
shadcn/ui の公式ドキュメントは充実していますが、60 種類以上のコンポーネントから目的のものを探すには時間がかかります。
各コンポーネントのページを順番に確認していく方法では、以下のような無駄が発生してしまうのです:
- 類似コンポーネントを複数確認する時間
- API リファレンスを読み込む時間
- 実装例を比較検討する時間
初めて shadcn/ui を使う開発者であれば、適切なコンポーネントを見つけるまでに 30 分から 1 時間かかることも珍しくありません。
用途とコンポーネントのミスマッチ
適切でないコンポーネントを選択すると、以下のような問題が発生します:
- ユーザビリティの低下(操作しにくい UI)
- アクセシビリティの問題(スクリーンリーダー非対応など)
- 過剰な実装(シンプルで済むところに複雑なコンポーネント)
- パフォーマンスの悪化(不要な機能を持つ重いコンポーネント)
以下の図は、コンポーネント選定で迷う典型的なフローを示しています。
mermaidflowchart TD
start["実装要件"] --> search["ドキュメント検索"]
search --> candidate1["候補1を発見"]
search --> candidate2["候補2を発見"]
search --> candidate3["候補3を発見"]
candidate1 --> compare["比較検討"]
candidate2 --> compare
candidate3 --> compare
compare --> uncertain{"確信が持てない"}
uncertain -->|再検索| search
uncertain -->|試作| prototype["プロトタイプ作成"]
prototype --> test["動作確認"]
test --> mismatch{"要件と合わない"}
mismatch -->|作り直し| search
mismatch -->|OK| done["実装完了"]
このような試行錯誤を繰り返すことで、開発時間が大幅に増加してしまいます。
解決策
用途ベースのコンポーネント選定アプローチ
コンポーネントの名前や機能から探すのではなく、「何を実現したいか」という用途を起点に選定することで、最短ルートでたどり着けます。
このアプローチでは、以下のステップでコンポーネントを選定するのです:
- 用途の明確化:実装したい機能を一言で表現する
- カテゴリの特定:6 つのカテゴリのどれに該当するか判断
- 早見表で検索:該当カテゴリの早見表から候補を絞り込む
- 代替候補の確認:推奨コンポーネントが要件に合わない場合の選択肢を確認
以下の図は、この選定フローを視覚化したものです。
mermaidflowchart LR
purpose["用途を定義"] --> category["カテゴリ特定"]
category --> table_ref["早見表参照"]
table_ref --> primary["推奨コンポーネント"]
table_ref --> alternative["代替候補"]
primary --> check{"要件に合致?"}
check -->|Yes| implement["実装"]
check -->|No| alternative
alternative --> implement
このフローに従えば、迷う時間を最小限に抑えられるでしょう。
カテゴリ別の選定基準
各カテゴリには明確な選定基準があります。以下の表は、カテゴリごとの判断ポイントをまとめたものです。
| # | カテゴリ | 判断ポイント | よくある用途 |
|---|---|---|---|
| 1 | データ表示系 | 情報を見せるだけで操作は不要 | 一覧、統計、プロフィール |
| 2 | フォーム・入力系 | ユーザーからの入力を受け付ける | 登録、設定、検索 |
| 3 | ナビゲーション系 | ページや機能への移動を提供 | メニュー、パンくず、検索 |
| 4 | フィードバック系 | システムの状態や結果を伝える | 通知、エラー、確認 |
| 5 | レイアウト系 | コンテンツの配置や区切りを管理 | セクション、折りたたみ |
| 6 | オーバーレイ系 | 既存画面の上に表示する | モーダル、ドロワー |
推奨と代替の使い分け
早見表では各用途に対して「推奨コンポーネント」と「代替候補」を示していますが、これらの使い分けは以下の基準で判断します。
推奨コンポーネントを選ぶべき場合
- 一般的な用途で標準的な実装を求める
- 開発時間を最優先したい
- アクセシビリティを重視する
代替候補を選ぶべき場合
- 特殊な要件やカスタマイズが必要
- デザインの制約がある
- パフォーマンスを最適化したい
具体例
データ表示系の選定例
データ表示系コンポーネントは、情報を視覚的に整理して提示する役割を担います。ここでは代表的なシナリオでの選定方法を見ていきましょう。
シナリオ 1:商品一覧ページの実装
EC サイトで商品一覧を表示する場合、Table コンポーネントが最適です。
Table コンポーネントの基本実装
まず、必要な型定義を準備します。
typescript// types/product.ts
export interface Product {
id: string;
name: string;
price: number;
stock: number;
category: string;
}
次に、Table コンポーネントをインポートします。
typescript// components/product-list.tsx
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table';
商品データを定義し、テーブルで表示するコンポーネントを作成します。
typescriptexport function ProductList() {
// サンプルデータ
const products: Product[] = [
{ id: "1", name: "ノートPC", price: 89800, stock: 15, category: "電化製品" },
{ id: "2", name: "マウス", price: 2980, stock: 50, category: "周辺機器" },
{ id: "3", name: "キーボード", price: 8900, stock: 30, category: "周辺機器" },
]
Table コンポーネントを使ってデータを表示します。
typescript return (
<Table>
<TableHeader>
<TableRow>
<TableHead>商品名</TableHead>
<TableHead>カテゴリ</TableHead>
<TableHead className="text-right">価格</TableHead>
<TableHead className="text-right">在庫</TableHead>
</TableRow>
</TableHeader>
データをマッピングして各行を表示します。
typescript <TableBody>
{products.map((product) => (
<TableRow key={product.id}>
<TableCell className="font-medium">{product.name}</TableCell>
<TableCell>{product.category}</TableCell>
<TableCell className="text-right">
¥{product.price.toLocaleString()}
</TableCell>
<TableCell className="text-right">{product.stock}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
)
}
このように、Table コンポーネントを使えば構造化されたデータを簡潔に表示できます。
シナリオ 2:ダッシュボードの KPI 表示
管理画面のダッシュボードで統計情報を表示する場合は、Card と Badge の組み合わせが効果的です。
Card と Badge の組み合わせ実装
必要なコンポーネントをインポートします。
typescript// components/kpi-card.tsx
import {
Card,
CardContent,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
KPI データの型を定義します。
typescriptinterface KPICardProps {
title: string;
value: string;
change: number; // 前月比などの変化率
trend: 'up' | 'down' | 'stable';
}
KPI カードコンポーネントを作成します。
typescriptexport function KPICard({ title, value, change, trend }: KPICardProps) {
// トレンドに応じたバッジの色を決定
const badgeVariant = trend === "up" ? "default" :
trend === "down" ? "destructive" :
"secondary"
Card コンポーネント内に KPI 情報を配置します。
typescript return (
<Card>
<CardHeader className="flex flex-row items-center justify-between space-y-0 pb-2">
<CardTitle className="text-sm font-medium">{title}</CardTitle>
<Badge variant={badgeVariant}>
{trend === "up" ? "↑" : trend === "down" ? "↓" : "→"} {Math.abs(change)}%
</Badge>
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{value}</div>
</CardContent>
</Card>
)
}
実際の使用例では、複数の KPI カードを並べて表示します。
typescript// pages/dashboard.tsx
export function Dashboard() {
return (
<div className='grid gap-4 md:grid-cols-2 lg:grid-cols-4'>
<KPICard
title='総売上'
value='¥12,450,000'
change={12.5}
trend='up'
/>
<KPICard
title='新規顧客'
value='245'
change={-5.2}
trend='down'
/>
<KPICard
title='アクティブユーザー'
value='1,234'
change={0.1}
trend='stable'
/>
<KPICard
title='注文数'
value='892'
change={8.3}
trend='up'
/>
</div>
);
}
Card と Badge を組み合わせることで、視覚的に分かりやすい KPI ダッシュボードを構築できます。
フォーム・入力系の選定例
フォーム・入力系コンポーネントは、ユーザーからのデータ入力を受け付ける際に使用します。用途に応じた適切な選択が、ユーザビリティに大きく影響するのです。
シナリオ 3:ユーザー登録フォーム
ユーザー登録フォームでは、複数の入力タイプを組み合わせる必要があります。
基本的なフォーム構造
フォーム関連のコンポーネントをインポートします。
typescript// components/registration-form.tsx
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { Button } from '@/components/ui/button';
テキスト入力フィールドの実装です。
typescriptexport function RegistrationForm() {
return (
<form className="space-y-6">
{/* 名前入力 */}
<div className="space-y-2">
<Label htmlFor="name">お名前</Label>
<Input id="name" placeholder="山田 太郎" required />
</div>
メールアドレス入力には適切な type 属性を指定します。
typescript{
/* メールアドレス入力 */
}
<div className='space-y-2'>
<Label htmlFor='email'>メールアドレス</Label>
<Input
id='email'
type='email'
placeholder='example@email.com'
required
/>
</div>;
性別選択には Radio Group ではなく、選択肢が少ない場合でも Select を使うケースもあります。
typescript{
/* 性別選択 */
}
<div className='space-y-2'>
<Label htmlFor='gender'>性別</Label>
<Select>
<SelectTrigger id='gender'>
<SelectValue placeholder='選択してください' />
</SelectTrigger>
<SelectContent>
<SelectItem value='male'>男性</SelectItem>
<SelectItem value='female'>女性</SelectItem>
<SelectItem value='other'>その他</SelectItem>
<SelectItem value='no-answer'>回答しない</SelectItem>
</SelectContent>
</Select>
</div>;
利用規約の同意には Checkbox を使用します。
typescript{
/* 利用規約同意 */
}
<div className='flex items-center space-x-2'>
<Checkbox id='terms' required />
<Label htmlFor='terms' className='text-sm font-normal'>
利用規約とプライバシーポリシーに同意します
</Label>
</div>;
送信ボタンを配置してフォームを完成させます。
typescript <Button type="submit" className="w-full">
登録する
</Button>
</form>
)
}
このように、用途に応じて異なる入力コンポーネントを適切に組み合わせることが重要です。
シナリオ 4:検索可能なタグ選択
記事投稿フォームなどで、既存のタグから選択したり、新しいタグを追加したりする場合は、Combobox が最適でしょう。
Combobox の実装
Combobox と関連コンポーネントをインポートします。
typescript// components/tag-selector.tsx
import { Combobox } from '@/components/ui/combobox';
import { useState } from 'react';
タグデータと選択状態を管理します。
typescriptexport function TagSelector() {
const [selectedTags, setSelectedTags] = useState<string[]>([])
// 利用可能なタグのリスト
const availableTags = [
{ value: "react", label: "React" },
{ value: "typescript", label: "TypeScript" },
{ value: "nextjs", label: "Next.js" },
{ value: "tailwind", label: "Tailwind CSS" },
{ value: "shadcn", label: "shadcn/ui" },
]
Combobox は検索機能を持ち、大量の選択肢から絞り込めます。Select との違いは、この検索機能の有無です。
複数選択の場合は、状態管理と UI の更新が必要になります。このような高度な入力 UI では、Combobox が強力なツールとなるでしょう。
ナビゲーション系の選定例
ナビゲーション系コンポーネントは、ユーザーを目的の場所へ導く重要な役割を担います。
シナリオ 5:管理画面のサイドバーメニュー
管理画面のサイドバーには、Sheet と Navigation の組み合わせが効果的です。
Sheet を使ったサイドバーの実装
必要なコンポーネントをインポートします。
typescript// components/admin-sidebar.tsx
import {
Sheet,
SheetContent,
SheetTrigger,
} from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { Menu } from 'lucide-react';
メニュー項目を定義します。
typescriptconst menuItems = [
{ label: 'ダッシュボード', href: '/admin/dashboard' },
{ label: 'ユーザー管理', href: '/admin/users' },
{ label: '商品管理', href: '/admin/products' },
{ label: '注文管理', href: '/admin/orders' },
{ label: '設定', href: '/admin/settings' },
];
Sheet コンポーネントでサイドバーを実装します。
typescriptexport function AdminSidebar() {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="outline" size="icon">
<Menu className="h-4 w-4" />
</Button>
</SheetTrigger>
SheetContent にメニュー項目を配置します。
typescript <SheetContent side="left">
<nav className="flex flex-col space-y-4">
{menuItems.map((item) => (
<a
key={item.href}
href={item.href}
className="text-sm font-medium hover:underline"
>
{item.label}
</a>
))}
</nav>
</SheetContent>
</Sheet>
)
}
Sheet はモバイル対応のドロワーとしても機能し、レスポンシブなナビゲーションを実現できます。
フィードバック系の選定例
フィードバック系コンポーネントは、システムの状態や処理結果をユーザーに伝える役割を果たします。
シナリオ 6:保存成功の通知
フォーム送信後の成功メッセージには、Toast コンポーネントが最適です。
Toast の実装
Toast フックをインポートします。
typescript// components/settings-form.tsx
import { useToast } from '@/components/ui/use-toast';
import { Button } from '@/components/ui/button';
Toast フックを使って通知を表示します。
typescriptexport function SettingsForm() {
const { toast } = useToast()
const handleSave = () => {
// 保存処理(省略)
// 成功通知を表示
toast({
title: "保存しました",
description: "設定が正常に保存されました。",
})
}
エラー時は異なるバリアントを使用します。
typescriptconst handleError = () => {
toast({
title: 'エラーが発生しました',
description:
'設定の保存に失敗しました。もう一度お試しください。',
variant: 'destructive',
});
};
Toast は一時的な通知に適しており、ユーザーの作業を妨げません。一方、Alert は永続的な情報表示に適しています。
シナリオ 7:削除確認ダイアログ
重要な操作の確認には、Alert Dialog を使用します。
Alert Dialog の実装
Alert Dialog 関連のコンポーネントをインポートします。
typescript// components/delete-confirmation.tsx
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from '@/components/ui/alert-dialog';
import { Button } from '@/components/ui/button';
削除確認ダイアログのコンポーネントを作成します。
typescriptexport function DeleteConfirmation({ itemName, onConfirm }: {
itemName: string
onConfirm: () => void
}) {
return (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button variant="destructive">削除</Button>
</AlertDialogTrigger>
ダイアログの内容を定義します。
typescript <AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>本当に削除しますか?</AlertDialogTitle>
<AlertDialogDescription>
{itemName}を削除します。この操作は取り消せません。
</AlertDialogDescription>
</AlertDialogHeader>
キャンセルと確認のボタンを配置します。
typescript <AlertDialogFooter>
<AlertDialogCancel>キャンセル</AlertDialogCancel>
<AlertDialogAction onClick={onConfirm}>
削除する
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
)
}
Alert Dialog は、ユーザーに明示的な確認を求める場合に使用し、通常の Dialog は情報表示や複雑な入力に使用します。
レイアウト系とオーバーレイ系の選定例
レイアウト系とオーバーレイ系のコンポーネントは、画面構成を整える役割を担います。
シナリオ 8:折りたたみ可能な FAQ
FAQ ページでは、Accordion コンポーネントが最適でしょう。
Accordion の実装
Accordion 関連のコンポーネントをインポートします。
typescript// components/faq.tsx
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/ui/accordion';
FAQ 項目を配置します。
typescriptexport function FAQ() {
return (
<Accordion type="single" collapsible className="w-full">
<AccordionItem value="item-1">
<AccordionTrigger>shadcn/uiとは何ですか?</AccordionTrigger>
<AccordionContent>
shadcn/uiは、Reactプロジェクト向けのUIコンポーネントライブラリです。
コンポーネントをプロジェクトに直接コピーして使用するため、
完全なカスタマイズが可能です。
</AccordionContent>
</AccordionItem>
複数の項目を追加できます。
typescript <AccordionItem value="item-2">
<AccordionTrigger>インストール方法を教えてください</AccordionTrigger>
<AccordionContent>
CLIを使用して、必要なコンポーネントを個別にインストールできます。
yarn dlx shadcn-ui@latest add [component-name] を実行してください。
</AccordionContent>
</AccordionItem>
</Accordion>
)
}
Accordion は複数の項目を省スペースで表示でき、必要な情報だけを展開できます。
シナリオ 9:フィルター設定パネル
商品一覧のフィルター設定には、Sheet コンポーネントが便利です。
Sheet を使ったフィルターパネル
Sheet とフォームコンポーネントをインポートします。
typescript// components/filter-panel.tsx
import {
Sheet,
SheetContent,
SheetHeader,
SheetTitle,
SheetTrigger,
} from '@/components/ui/sheet';
import { Button } from '@/components/ui/button';
import { Slider } from '@/components/ui/slider';
import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
フィルターパネルのトリガーボタンを配置します。
typescriptexport function FilterPanel() {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="outline">フィルター</Button>
</SheetTrigger>
フィルター設定の UI を構築します。
typescript <SheetContent>
<SheetHeader>
<SheetTitle>絞り込み条件</SheetTitle>
</SheetHeader>
<div className="space-y-6 py-4">
{/* 価格帯フィルター */}
<div className="space-y-2">
<Label>価格帯</Label>
<Slider defaultValue={[0, 100000]} max={100000} step={1000} />
</div>
カテゴリ選択のチェックボックスを配置します。
typescript {/* カテゴリフィルター */}
<div className="space-y-2">
<Label>カテゴリ</Label>
<div className="space-y-2">
<div className="flex items-center space-x-2">
<Checkbox id="electronics" />
<Label htmlFor="electronics">電化製品</Label>
</div>
<div className="flex items-center space-x-2">
<Checkbox id="accessories" />
<Label htmlFor="accessories">周辺機器</Label>
</div>
</div>
</div>
</div>
</SheetContent>
</Sheet>
)
}
Sheet はサイドから表示されるパネルとして、フィルター設定やオプション選択に最適です。
まとめ
shadcn/ui の豊富なコンポーネントから最適なものを選ぶには、用途ベースのアプローチが効果的です。
本記事で紹介した早見表を活用することで、以下のメリットが得られます:
開発効率の向上
用途から逆引きすることで、コンポーネント選定の時間を大幅に削減できます。ドキュメントを隅々まで読む必要がなくなり、すぐに実装を開始できるでしょう。
適切なコンポーネント選択
推奨コンポーネントと代替候補を明示することで、要件に最も適した選択が可能になります。ユーザビリティとアクセシビリティを損なうリスクが減少するのです。
チーム内の統一性
早見表を共有することで、チーム内でコンポーネント選定の基準が統一されます。コードレビューでの指摘も減り、一貫性のある UI が実現できますね。
shadcn/ui は今後もコンポーネントが追加されていくでしょう。この選定マップを基準として、新しいコンポーネントも体系的に理解していけます。
早見表を手元に置きながら、快適な shadcn/ui 開発を楽しんでください。
関連リンク
articleshadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表
articleshadcn/ui CLI 完全活用:add/update のカスタムテンプレート運用術
articleshadcn/ui のバンドルサイズ影響を検証:Tree Shaking・Code Split の実測データ
articleshadcn/ui × RSC 時代のフロント設計:Server/Client の最適境界を見極める指針
articleshadcn/ui のテンプレート差分を追従する運用:更新検知・差分マージ・回帰防止
articleshadcn/ui で Tailwind クラスが競合する時の対処法:優先度・レイヤ・@apply の整理
articlePinia ストアスキーマの変更管理:バージョン付与・マイグレーション・互換ポリシー
articleshadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表
articleOllama のコスト最適化:モデルサイズ・VRAM 使用量・バッチ化の実践
articleRemix Loader/Action チートシート:Request/Response API 逆引き大全
articleObsidian タスク運用の最適解:Tasks + Periodic Notes で計画と実行を接続
articlePreact Signals チートシート:signal/computed/effect 実用スニペット 30
blogiPhone 17シリーズの発表!全モデルiPhone 16から進化したポイントを見やすく整理
blogGoogleストアから訂正案内!Pixel 10ポイント有効期限「1年」表示は誤りだった
blog【2025年8月】Googleストア「ストアポイント」は1年表記はミス?2年ルールとの整合性を検証
blogGoogleストアの注文キャンセルはなぜ起きる?Pixel 10購入前に知るべき注意点
blogPixcel 10シリーズの発表!全モデル Pixcel 9 から進化したポイントを見やすく整理
blogフロントエンドエンジニアの成長戦略:コーチングで最速スキルアップする方法
review今の自分に満足していますか?『持たざる者の逆襲 まだ何者でもない君へ』溝口勇児
reviewついに語られた業界の裏側!『フジテレビの正体』堀江貴文が描くテレビ局の本当の姿
review愛する勇気を持てば人生が変わる!『幸せになる勇気』岸見一郎・古賀史健のアドラー実践編で真の幸福を手に入れる
review週末を変えれば年収も変わる!『世界の一流は「休日」に何をしているのか』越川慎司の一流週末メソッド
review新しい自分に会いに行こう!『自分の変え方』村岡大樹の認知科学コーチングで人生リセット
review科学革命から AI 時代へ!『サピエンス全史 下巻』ユヴァル・ノア・ハラリが予見する人類の未来