shadcn/ui入門 - 再利用可能なUIコンポーネント

beginner | 40分 で読める | 2025.12.13

このチュートリアルで学ぶこと

✓ shadcn/uiセットアップ
✓ コンポーネント追加
✓ テーマカスタマイズ
✓ フォーム構築
✓ ダークモード

Step 1: セットアップ

npx create-next-app@latest my-app --typescript --tailwind
cd my-app
npx shadcn-ui@latest init

初期設定で以下を選択:

  • TypeScript: yes
  • Style: Default
  • Base color: Slate
  • CSS variables: yes

Step 2: コンポーネント追加

# 個別追加
npx shadcn-ui@latest add button
npx shadcn-ui@latest add card
npx shadcn-ui@latest add input
npx shadcn-ui@latest add form

# 複数追加
npx shadcn-ui@latest add button card input dialog

Step 3: 基本的な使用

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Input } from '@/components/ui/input';

export default function HomePage() {
  return (
    <div className="p-8">
      <Card className="max-w-md">
        <CardHeader>
          <CardTitle>ログイン</CardTitle>
        </CardHeader>
        <CardContent className="space-y-4">
          <Input placeholder="メールアドレス" />
          <Input type="password" placeholder="パスワード" />
          <Button className="w-full">ログイン</Button>
        </CardContent>
      </Card>
    </div>
  );
}

Step 4: バリアント

<Button variant="default">Default</Button>
<Button variant="destructive">Delete</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>

<Button size="sm">Small</Button>
<Button size="default">Default</Button>
<Button size="lg">Large</Button>

Step 5: フォーム構築

npx shadcn-ui@latest add form
npm install zod react-hook-form @hookform/resolvers
'use client';
import { zodResolver } from '@hookform/resolvers/zod';
import { useForm } from 'react-hook-form';
import { z } from 'zod';
import { Button } from '@/components/ui/button';
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from '@/components/ui/form';
import { Input } from '@/components/ui/input';

const schema = z.object({
  email: z.string().email('有効なメールアドレスを入力'),
  password: z.string().min(8, '8文字以上'),
});

export function LoginForm() {
  const form = useForm({
    resolver: zodResolver(schema),
    defaultValues: { email: '', password: '' },
  });

  const onSubmit = (data: z.infer<typeof schema>) => {
    console.log(data);
  };

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>メール</FormLabel>
              <FormControl>
                <Input {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <FormField
          control={form.control}
          name="password"
          render={({ field }) => (
            <FormItem>
              <FormLabel>パスワード</FormLabel>
              <FormControl>
                <Input type="password" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit" className="w-full">ログイン</Button>
      </form>
    </Form>
  );
}

Step 6: ダイアログ

import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from '@/components/ui/dialog';

export function ConfirmDialog() {
  return (
    <Dialog>
      <DialogTrigger asChild>
        <Button variant="destructive">削除</Button>
      </DialogTrigger>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>本当に削除しますか?</DialogTitle>
          <DialogDescription>
            この操作は取り消せません。
          </DialogDescription>
        </DialogHeader>
        <div className="flex justify-end gap-2">
          <Button variant="outline">キャンセル</Button>
          <Button variant="destructive">削除</Button>
        </div>
      </DialogContent>
    </Dialog>
  );
}

Step 7: テーマカスタマイズ

/* globals.css */
@layer base {
  :root {
    --primary: 222.2 47.4% 11.2%;
    --primary-foreground: 210 40% 98%;
    /* カスタムカラー */
  }

  .dark {
    --primary: 210 40% 98%;
    --primary-foreground: 222.2 47.4% 11.2%;
  }
}

まとめ

shadcn/uiはコピー&ペースト型のUIライブラリで、完全なカスタマイズ性を持ちます。Radix UIとTailwind CSSをベースにしています。

← 一覧に戻る