T-CREATOR

shadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表

shadcn/ui コンポーネント置換マップ:用途別に最短でたどり着く選定表

shadcn/ui は豊富なコンポーネントを提供していますが、「この機能を実装したいけど、どのコンポーネントを使えばいいんだろう?」と迷った経験はありませんか。

60 種類以上のコンポーネントから最適なものを選ぶのは、初心者にとってもベテラン開発者にとっても時間のかかる作業です。本記事では、用途別に shadcn/ui コンポーネントを即座に見つけられる選定マップを提供します。

早見表を活用すれば、迷う時間を削減し、開発スピードを大幅に向上させられるでしょう。

コンポーネント早見表

データ表示系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1表形式データ表示TableData Table商品一覧、ユーザーリスト
2カード型表示Card-ダッシュボード、記事一覧
3統計・数値表示Card + Badge-KPI、メトリクス表示
4プロフィール表示Avatar + Card-ユーザー情報、アカウント
5進捗状況表示Progress-アップロード、処理進行度
6ステータス表示Badge-タグ、状態ラベル
7階層データ表示AccordionCollapsibleFAQ、ネストメニュー
8タブ切り替え表示Tabs-設定画面、複数ビュー

フォーム・入力系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1テキスト入力InputTextarea名前、メール入力
2複数行テキストTextarea-コメント、説明文入力
3選択肢(少数)Radio GroupSelect性別、サイズ選択
4選択肢(多数)SelectCombobox国選択、カテゴリ選択
5検索可能選択ComboboxCommandタグ選択、ユーザー検索
6複数選択Checkbox-利用規約、オプション選択
7ON/OFF 切替SwitchCheckbox通知設定、機能有効化
8数値範囲選択SliderInput(number)価格帯、音量調整
9日付選択Calendar + PopoverInput(date)予約日、締切日設定
10ファイル選択Input(file) + Label-画像アップロード

ナビゲーション系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1メインメニューNavigation MenuMenubarヘッダーナビゲーション
2サイドメニューSheet + NavigationAccordion管理画面サイドバー
3パンくずリストBreadcrumb-ページ階層表示
4ページネーションPagination-一覧ページ
5コマンド検索CommandComboboxショートカットメニュー
6コンテキストメニューContext MenuDropdown Menu右クリックメニュー
7ドロップダウンDropdown MenuPopoverアクションメニュー

フィードバック系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1成功メッセージToastAlert保存完了通知
2エラー表示AlertToastフォームエラー
3確認ダイアログAlert DialogDialog削除確認
4情報ダイアログDialogSheet詳細情報表示
5ローディングSkeletonSpinner(custom)データ読込中
6ツールチップTooltipPopover補足説明
7ホバー情報Hover CardTooltipプレビュー表示

レイアウト系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1セクション区切りSeparator-コンテンツ区切り
2折りたたみCollapsibleAccordionオプション表示・非表示
3スクロール領域Scroll Areadiv(overflow)長いリスト
4アスペクト比固定Aspect Ratiodiv(padding-trick)動画埋め込み
5リサイズ可能Resizable-分割パネル

オーバーレイ系コンポーネント

#用途推奨コンポーネント代替候補使用場面
1モーダルDialogAlert Dialogフォーム入力画面
2サイドパネルSheetDialogフィルター設定
3ポップアップPopoverTooltip追加情報表示
4ドロワー(モバイル)SheetDialogモバイルメニュー

背景

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 種類以上のコンポーネントから目的のものを探すには時間がかかります。

各コンポーネントのページを順番に確認していく方法では、以下のような無駄が発生してしまうのです:

  1. 類似コンポーネントを複数確認する時間
  2. API リファレンスを読み込む時間
  3. 実装例を比較検討する時間

初めて 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["実装完了"]

このような試行錯誤を繰り返すことで、開発時間が大幅に増加してしまいます。

解決策

用途ベースのコンポーネント選定アプローチ

コンポーネントの名前や機能から探すのではなく、「何を実現したいか」という用途を起点に選定することで、最短ルートでたどり着けます。

このアプローチでは、以下のステップでコンポーネントを選定するのです:

  1. 用途の明確化:実装したい機能を一言で表現する
  2. カテゴリの特定:6 つのカテゴリのどれに該当するか判断
  3. 早見表で検索:該当カテゴリの早見表から候補を絞り込む
  4. 代替候補の確認:推奨コンポーネントが要件に合わない場合の選択肢を確認

以下の図は、この選定フローを視覚化したものです。

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 開発を楽しんでください。

関連リンク