mcpField
V
v0

v0

github.com/headline-designデザイン・UI1354 回インストール24 週間前に更新
リポジトリ

v0 について

Webアプリのデザインと開発に関するガイド型スキルです。ビジュアル設計、コンポーネント構成、Tailwind CSS、アクセシビリティ、パフォーマンスを扱い、一貫したUI実装を支援します。

主な機能

  1. 01カラーとタイポグラフィの指針
  2. 02レイアウトとレスポンシブ設計
  3. 03コンポーネント構成とコード整理
  4. 04Tailwind CSSのパターン
  5. 05アクセシビリティと性能の実践

活用シーン

  1. 01Webアプリの画面設計
  2. 02再利用可能なUIコンポーネントの整理
  3. 03レスポンシブ設計とアクセシビリティの確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/headline-design/design-craft --skill v0

インストール後、Claude Code で/v0を入力して読み込まれたか確認します。

同梱ファイルREADME.md

詳細

v0 デザイン&開発スキル

優れた UI/UX を備えた、プロフェッショナル品質で視覚的にも魅力的な Web アプリケーションを作成するための総合ガイドです。


目次

  1. デザイン哲学
  2. カラーシステム
  3. タイポグラフィ
  4. レイアウトと余白
  5. コンポーネントのアーキテクチャ
  6. Tailwind CSS のパターン
  7. アクセシビリティ
  8. パフォーマンス
  9. コードの構成
  10. UI/UX の原則
  11. 一般的なパターン
  12. 避けるべきアンチパターン

デザイン哲学

基本原則
  1. 足し過ぎず、抑制する — 優れたデザインとは、何を加えるかではなく、何を省くかです
  2. 巧妙さより明快さ — ユーザーがインターフェースをすぐに理解できるようにします
  3. 新しさより一貫性 — 予測しやすいパターンは認知負荷を軽減します
  4. 装飾より目的 — すべての要素に、そこにある理由が必要です
  5. 魅力的なものをリリースし、決して醜くしない — 創造性と仕上がりの美しさを両立させます
v0 の美学
  • 余白を十分に取った、クリーンでモダンなインターフェース
  • 邪魔にならずに奥行きを生み出す、控えめな影と境界線
  • 視線を誘導する、滑らかで意図のあるアニメーション
  • 統一感のある、プロフェッショナルなカラーパレット
  • 明確な階層を生み出すタイポグラフィ

カラーシステム

3〜5 色のルール

必ず、色は合計でちょうど 3〜5 色を使用してください。 この制約により、統一感が生まれます。

必須の構成
1 Primary Brand Color     → CTAs, key actions, brand identity
2-3 Neutrals              → Backgrounds, text, borders
1-2 Accent Colors         → Status indicators, highlights, secondary actions
色選びのガイドライン
用途推奨事項
主なアクション彩度が高く、アクセシビリティに配慮したブランドカラー
背景オフホワイト、ソフトグレー(広い領域には純白を使用しない)
テキスト黒に近い色(#0a0a0a〜#1a1a1a)。純粋な黒は使用しない
境界線/区切り線ごく控えめなグレー(不透明度 10〜20%)
成功状態ティール系のグリーン
エラー状態刺激の強すぎない、暖色系の赤
警告状態アンバー/オレンジ系
色温度のルール
  • 使う: 類似色。青→ティール、紫→ピンク、オレンジ→赤
  • 使わない: 対照的な色温度の組み合わせ。ピンク→緑、オレンジ→青、赤→シアン
グラデーションのルール
  • 明示的に求められない限り、グラデーションは避けてください — 単色のほうがすっきりします
  • グラデーションが必要な場合:
    • 控えめなアクセントとしてのみ使用し、主要な要素には使用しない
    • 色の停止点は最大 2〜3 色
    • 類似色のみを使用する
    • グラデーションの方向を考慮する(通常は上から下、または斜め)
デザイントークンの構成

CSS 変数では、常に意味的なデザイントークンを使用します。

:root {
  /* Backgrounds */
  --background: 0 0% 100%;
  --foreground: 0 0% 3.9%;

  /* Cards & Surfaces */
  --card: 0 0% 100%;
  --card-foreground: 0 0% 3.9%;

  /* Primary Actions */
  --primary: 0 0% 9%;
  --primary-foreground: 0 0% 98%;

  /* Secondary Actions */
  --secondary: 0 0% 96.1%;
  --secondary-foreground: 0 0% 9%;

  /* Muted Elements */
  --muted: 0 0% 96.1%;
  --muted-foreground: 0 0% 45.1%;

  /* Accents */
  --accent: 0 0% 96.1%;
  --accent-foreground: 0 0% 9%;

  /* Destructive Actions */
  --destructive: 0 84.2% 60.2%;
  --destructive-foreground: 0 0% 98%;

  /* Borders & Inputs */
  --border: 0 0% 89.8%;
  --input: 0 0% 89.8%;
  --ring: 0 0% 3.9%;

  /* Radius */
  --radius: 0.5rem;
}

重要なルール: text-white、bg-black のような色の直接指定は決して使用しないでください。すべてトークンを通じてテーマを適用する必要があります。


タイポグラフィ

フォントは最大 2 種類のルール

フォントファミリーは必ず最大 2 種類までにしてください。 フォントが増えると、見た目にまとまりがなくなります。

フォントの組み合わせ方
Headings: Display or Sans-serif with personality (multiple weights)
Body: Highly readable sans-serif or serif
おすすめの組み合わせ
スタイル見出し本文
モダンテックInter, GeistInter, Geist
エディトリアルPlayfair DisplaySource Sans Pro
スタートアップCal Sans, ManropeInter
コーポレートOutfitSystem UI
クリエイティブSpace GroteskDM Sans
タイポグラフィのスケール

明確な階層を持つ、一貫したスケールを使用します。

/* Recommended Tailwind Classes */
text-xs    → 12px  → Fine print, labels
text-sm    → 14px  → Secondary text, captions
text-base  → 16px  → Body text (minimum for readability)
text-lg    → 18px  → Lead paragraphs
text-xl    → 20px  → Section headers
text-2xl   → 24px  → Card titles
text-3xl   → 30px  → Page sections
text-4xl   → 36px  → Hero subheadings
text-5xl   → 48px  → Hero headings
text-6xl+  → 60px+ → Display headings (use sparingly)
行の高さのルール
  • 本文: leading-relaxed(1.625)、または leading-6〜leading-7
  • 見出し: leading-tight(1.25)、または leading-snug(1.375)
  • 本文にはデフォルトの行の高さを決して使用しないでください。詰まりすぎています
テキストの折り返し
  • 最適な位置で改行されるよう、タイトルを text-balance で囲みます
  • 重要なコピーには text-pretty を使用します
  • 読みやすい行の長さにするため、max-w-prose または max-w-2xl を設定します
Next.js でのフォント実装
// layout.tsx
import { Inter, Playfair_Display } from 'next/font/google'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-sans'
})

const playfair = Playfair_Display({
  subsets: ['latin'],
  variable: '--font-serif'
})

export default function RootLayout({ children }) {
  return (
    <html className={`${inter.variable} ${playfair.variable}`}>
      <body className="font-sans">{children}</body>
    </html>
  )
}
// tailwind.config.js
module.exports = {
  theme: {
    extend: {
      fontFamily: {
        sans: ['var(--font-sans)'],
        serif: ['var(--font-serif)'],
      },
    },
  },
}

レイアウトと余白

モバイルファーストのデザイン

必ずモバイルファーストでデザインし、その後、大きな画面向けに調整します。

// ✅ Mobile-first approach
<div className="px-4 md:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">

// ❌ Desktop-first (avoid)
<div className="px-8 md:px-6 sm:px-4">
レイアウト手法の優先順位

レイアウトを決める際は、次の優先順位に従ってください。

  1. Flexbox — ほとんどのレイアウト(ナビゲーションバー、カード、シンプルなグリッド)
  2. CSS Grid — 複雑な2次元レイアウト、ベントーグリッド、ダッシュボード
  3. 絶対配置 — 必要な場合に限る(モーダル、ツールチップ)
  4. floatは使用しない
余白のスケール

Tailwindの余白スケールを一貫して使用してください。

4px  = p-1   → Tiny gaps (icon padding)
8px  = p-2   → Small gaps (button padding)
12px = p-3   → Compact spacing
16px = p-4   → Standard spacing (most common)
24px = p-6   → Comfortable spacing
32px = p-8   → Section spacing
48px = p-12  → Large section gaps
64px = p-16  → Hero spacing
96px = p-24  → Major section dividers
余白のルール
// ✅ Use gap for flex/grid spacing
<div className="flex gap-4">
<div className="grid gap-6">

// ✅ Use padding for container spacing
<section className="px-4 py-12 md:px-6 lg:py-24">

// ❌ Avoid space-* utilities
<div className="space-y-4">  // Less flexible

// ❌ Never mix gap and margin on same element
<div className="flex gap-4 mb-4">  // Pick one approach
コンテナのパターン
// Standard content container
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">

// Narrow content (articles, forms)
<div className="mx-auto max-w-2xl px-4">

// Full-bleed with contained content
<section className="w-full bg-muted">
  <div className="mx-auto max-w-7xl px-4 py-16">
レスポンシブブレークポイント
sm:  640px   → Large phones, small tablets
md:  768px   → Tablets
lg:  1024px  → Small laptops, tablets landscape
xl:  1280px  → Desktops
2xl: 1536px  → Large desktops

コンポーネントアーキテクチャ

ファイル構成
components/
├── ui/                    # Base shadcn components (don't modify)
│   ├── button.tsx
│   ├── card.tsx
│   └── ...
├── [feature]/             # Feature-specific components
│   ├── feature-header.tsx
│   ├── feature-card.tsx
│   └── feature-list.tsx
├── layout/                # Layout components
│   ├── header.tsx
│   ├── footer.tsx
│   └── sidebar.tsx
└── shared/                # Shared/common components
    ├── logo.tsx
    ├── theme-toggle.tsx
    └── loading-state.tsx
コンポーネント設計の原則
  1. 単一責任 — 各コンポーネントは1つのことを適切に行います
  2. 設定より合成 — シンプルなパーツから複雑なUIを構築します
  3. カスタマイズにはPropsを使用 — ハードコードされた値ではなく、Propsを使用します
  4. 適切なデフォルト値 — すぐに使用でき、必要に応じてカスタマイズできます
コンポーネントのテンプレート
import { cn } from "@/lib/utils"

interface FeatureCardProps {
  title: string
  description: string
  icon?: React.ReactNode
  className?: string
  variant?: "default" | "highlighted"
}

export function FeatureCard({
  title,
  description,
  icon,
  className,
  variant = "default"
}: FeatureCardProps) {
  return (
    <div
      className={cn(
        "rounded-lg border p-6 transition-colors",
        variant === "default" && "bg-card hover:bg-accent",
        variant === "highlighted" && "bg-primary text-primary-foreground",
        className
      )}
    >
      {icon && (
        <div className="mb-4 text-muted-foreground">
          {icon}
        </div>
      )}
      <h3 className="font-semibold text-lg">{title}</h3>
      <p className="mt-2 text-sm text-muted-foreground">
        {description}
      </p>
    </div>
  )
}
ページの構成
// app/feature/page.tsx
import { FeatureHero } from "@/components/feature/feature-hero"
import { FeatureGrid } from "@/components/feature/feature-grid"
import { FeatureCTA } from "@/components/feature/feature-cta"

export default function FeaturePage() {
  return (
    <main>
      <FeatureHero />
      <FeatureGrid />
      <FeatureCTA />
    </main>
  )
}

モノリシックなページファイルは作成しないでください。 論理的なコンポーネントに分割してください。


Tailwind CSSのパターン

クラスの整理

クラスの順序を統一してください。

className={cn(
  // 1. Layout (display, position, sizing)
  "flex items-center justify-between",
  "relative w-full max-w-md",

  // 2. Spacing (margin, padding, gap)
  "p-4 gap-2",

  // 3. Typography
  "text-sm font-medium",

  // 4. Colors & Backgrounds
  "bg-background text-foreground",

  // 5. Borders & Shadows
  "rounded-lg border shadow-sm",

  // 6. Transitions & Animations
  "transition-colors duration-200",

  // 7. States (hover, focus, active)
  "hover:bg-accent focus:ring-2",

  // 8. Responsive overrides
  "md:p-6 lg:flex-row"
)}
よく使うユーティリティパターン
// Centering
"flex items-center justify-center"
"grid place-items-center"

// Card pattern
"rounded-lg border bg-card p-6 shadow-sm"

// Interactive element
"cursor-pointer transition-colors hover:bg-accent"

// Focus ring (accessibility)
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"

// Truncation
"truncate"                    // Single line
"line-clamp-2"               // Multi-line (2 lines)

// Aspect ratios
"aspect-video"               // 16:9
"aspect-square"              // 1:1

// Backdrop blur (modals, overlays)
"bg-background/80 backdrop-blur-sm"

// Dividers
"divide-y divide-border"

// Screen reader only
"sr-only"
レスポンシブデザインのパターン
// Stack to row
<div className="flex flex-col gap-4 md:flex-row">

// Grid columns
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">

// Hide/show
<div className="hidden md:block">    // Show on md+
<div className="md:hidden">          // Hide on md+

// Responsive text
<h1 className="text-3xl md:text-4xl lg:text-5xl">

// Responsive spacing
<section className="py-12 md:py-16 lg:py-24">
アニメーションのパターン
// Subtle hover lift
"transition-transform hover:-translate-y-1"

// Fade in on hover
"opacity-0 group-hover:opacity-100 transition-opacity"

// Scale on hover
"transition-transform hover:scale-105"

// Color transition
"transition-colors hover:bg-accent"

// Combined
"transition-all duration-200 hover:shadow-lg hover:-translate-y-0.5"

アクセシビリティ

必須の実践事項
セマンティックHTML
// ✅ Correct
<main>
  <header>
    <nav aria-label="Main navigation">
  </header>
  <article>
    <h1>Page Title</h1>
    <section aria-labelledby="section-heading">
      <h2 id="section-heading">Section</h2>
    </section>
  </article>
  <footer>
</main>

// ❌ Avoid
<div className="header">
<div className="nav">
<div className="main">
フォーカス管理
// Visible focus states
"focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"

// Focus within (for form groups)
"focus-within:ring-2 focus-within:ring-ring"

// Skip link
<a
  href="#main-content"
  className="sr-only focus:not-sr-only focus:absolute focus:top-4 focus:left-4"
>
  Skip to content
</a>
スクリーンリーダーのサポート
// Hidden but accessible text
<span className="sr-only">Open menu</span>

// Aria labels
<button aria-label="Close dialog">
  <XIcon className="h-4 w-4" />
</button>

// Live regions for dynamic content
<div aria-live="polite" aria-atomic="true">
  {statusMessage}
</div>
画像のアクセシビリティ
// Informative images
<img src="/chart.png" alt="Sales increased 25% in Q4 2024" />

// Decorative images
<img src="/decoration.png" alt="" role="presentation" />

// Complex images
<figure>
  <img src="/diagram.png" alt="System architecture diagram" />
  <figcaption>
    Detailed description of the architecture...
  </figcaption>
</figure>
色のコントラスト
  • テキスト: コントラスト比を最低4.5:1にする(WCAG AA)
  • 大きなテキスト: コントラスト比を最低3:1にする
  • インタラクティブ要素: 視覚的に明確な違いを設ける
  • 情報を伝える際に色だけに頼らない
キーボード操作
// Interactive elements must be keyboard accessible
<button>Clickable</button>       // ✅ Naturally focusable
<div onClick={...}>Clickable</div>  // ❌ Not keyboard accessible

// If you must use a div:
<div
  role="button"
  tabIndex={0}
  onClick={handleClick}
  onKeyDown={(e) => e.key === 'Enter' && handleClick()}
>
  Clickable
</div>

パフォーマンス

画像の最適化
import Image from 'next/image'

// Always use Next.js Image component
<Image
  src="/hero.jpg"
  alt="Hero image description"
  width={1200}
  height={600}
  priority              // Above-the-fold images
  className="object-cover"
/>

// Responsive images
<Image
  src="/photo.jpg"
  alt="Description"
  fill
  sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
  className="object-cover"
/>
コード分割
// Dynamic imports for heavy components
import dynamic from 'next/dynamic'

const HeavyChart = dynamic(() => import('@/components/heavy-chart'), {
  loading: () => <ChartSkeleton />,
  ssr: false  // If client-only
})
読み込み状態
// Skeleton loading (preferred)
<div className="animate-pulse">
  <div className="h-4 w-3/4 rounded bg-muted" />
  <div className="mt-2 h-4 w-1/2 rounded bg-muted" />
</div>

// Spinner for actions
<Button disabled>
  <Loader2 className="mr-2 h-4 w-4 animate-spin" />
  Loading...
</Button>
データ取得
// ✅ Server Components for static data
async function ProductList() {
  const products = await getProducts()
  return <ProductGrid products={products} />
}

// ✅ SWR for client-side data
import useSWR from 'swr'

function UserProfile() {
  const { data, error, isLoading } = useSWR('/api/user', fetcher)

  if (isLoading) return <ProfileSkeleton />
  if (error) return <ErrorState />
  return <Profile user={data} />
}

// ❌ Never fetch in useEffect
useEffect(() => {
  fetch('/api/data').then(...)  // Anti-pattern
}, [])

コードの整理

プロジェクト構成
app/
├── (marketing)/          # Route groups for layouts
│   ├── page.tsx
│   ├── about/
│   └── pricing/
├── (dashboard)/
│   ├── layout.tsx
│   └── dashboard/
├── api/
│   └── [feature]/
│       └── route.ts
├── layout.tsx
└── globals.css

components/
├── ui/                   # shadcn components
├── [feature]/            # Feature components
├── layout/               # Layout components
└── shared/               # Shared components

lib/
├── utils.ts              # Utility functions
├── validations.ts        # Zod schemas
└── constants.ts          # App constants

hooks/
├── use-[feature].ts
└── use-media-query.ts

types/
└── index.ts
命名規則
種類規則例
コンポーネントPascalCaseFeatureCard.tsx
ファイルkebab-casefeature-card.tsx
フックuseを接頭辞とするcamelCaseuseFeature.ts
ユーティリティcamelCaseformatDate.ts
型PascalCaseFeatureProps
定数SCREAMING_SNAKE_CASEMAX_FILE_SIZE
CSS変数kebab-case--primary-color
インポートの整理
// 1. React/Next.js
import { useState, useEffect } from 'react'
import Image from 'next/image'
import Link from 'next/link'

// 2. Third-party libraries
import { motion } from 'framer-motion'
import { z } from 'zod'

// 3. Internal components
import { Button } from '@/components/ui/button'
import { FeatureCard } from '@/components/feature/feature-card'

// 4. Internal utilities/hooks
import { cn } from '@/lib/utils'
import { useFeature } from '@/hooks/use-feature'

// 5. Types
import type { Feature } from '@/types'

UI/UXの原則

視覚的な階層
  1. サイズ — 大きな要素ほど先に目を引きます
  2. 色 — 彩度の高い色はニュートラルな色より目立ちます
  3. コントラスト — 強いコントラストは視線を集めます
  4. 余白 — ホワイトスペースによって重要な要素を際立たせます
  5. 位置 — 左上から右下へと読むパターン
インタラクティブ状態

すべてのインタラクティブ要素に次の状態を用意してください。

// Button example
<button className={cn(
  // Default
  "bg-primary text-primary-foreground",
  // Hover
  "hover:bg-primary/90",
  // Focus
  "focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
  // Active/Pressed
  "active:scale-[0.98]",
  // Disabled
  "disabled:pointer-events-none disabled:opacity-50"
)}>
フィードバックのパターン
// Loading feedback
<Button disabled={isLoading}>
  {isLoading ? (
    <>
      <Loader2 className="mr-2 h-4 w-4 animate-spin" />
      Saving...
    </>
  ) : (
    'Save Changes'
  )}
</Button>

// Success feedback
<div className="flex items-center gap-2 text-green-600">
  <CheckCircle className="h-4 w-4" />
  <span>Changes saved successfully</span>
</div>

// Error feedback
<div className="rounded-md bg-destructive/10 p-4 text-destructive">
  <p className="text-sm font-medium">Error occurred</p>
  <p className="mt-1 text-sm opacity-90">{error.message}</p>
</div>
空の状態

空白の画面を表示しないでください。常に役立つ空の状態を用意してください。

<div className="flex flex-col items-center justify-center py-12 text-center">
  <InboxIcon className="h-12 w-12 text-muted-foreground/50" />
  <h3 className="mt-4 text-lg font-semibold">No messages yet</h3>
  <p className="mt-2 text-sm text-muted-foreground">
    When you receive messages, they&apos;ll appear here.
  </p>
  <Button className="mt-4">
    Send your first message
  </Button>
</div>
マイクロインタラクション

UXを高めるさりげないアニメーション:

// Hover lift effect
"transition-transform duration-200 hover:-translate-y-1 hover:shadow-lg"

// Button press effect
"active:scale-[0.98] transition-transform"

// Smooth reveals
"animate-in fade-in slide-in-from-bottom-4 duration-300"

// Skeleton pulse
"animate-pulse"

よく使うパターン

ヒーローセクション
<section className="relative overflow-hidden py-24 md:py-32 lg:py-40">
  <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
    <div className="mx-auto max-w-3xl text-center">
      <h1 className="text-balance text-4xl font-bold tracking-tight md:text-5xl lg:text-6xl">
        Your compelling headline here
      </h1>
      <p className="mt-6 text-pretty text-lg text-muted-foreground md:text-xl">
        Supporting text that elaborates on the headline and provides context.
      </p>
      <div className="mt-8 flex flex-col gap-4 sm:flex-row sm:justify-center">
        <Button size="lg">Primary Action</Button>
        <Button size="lg" variant="outline">Secondary Action</Button>
      </div>
    </div>
  </div>
</section>
機能グリッド
<section className="py-16 md:py-24">
  <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
    <div className="mx-auto max-w-2xl text-center">
      <h2 className="text-3xl font-bold md:text-4xl">Features</h2>
      <p className="mt-4 text-muted-foreground">
        Everything you need to succeed.
      </p>
    </div>
    <div className="mt-12 grid gap-8 sm:grid-cols-2 lg:grid-cols-3">
      {features.map((feature) => (
        <FeatureCard key={feature.id} {...feature} />
      ))}
    </div>
  </div>
</section>
カードグリッド
<div className="grid gap-6 sm:grid-cols-2 lg:grid-cols-3">
  {items.map((item) => (
    <Card key={item.id} className="group overflow-hidden">
      <div className="aspect-video overflow-hidden">
        <Image
          src={item.image}
          alt={item.title}
          fill
          className="object-cover transition-transform group-hover:scale-105"
        />
      </div>
      <CardHeader>
        <CardTitle>{item.title}</CardTitle>
        <CardDescription>{item.description}</CardDescription>
      </CardHeader>
      <CardFooter>
        <Button variant="ghost" className="ml-auto">
          Learn more <ArrowRight className="ml-2 h-4 w-4" />
        </Button>
      </CardFooter>
    </Card>
  ))}
</div>
ベントーグリッド
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
  {/* Large feature - spans 2 columns */}
  <div className="md:col-span-2 lg:row-span-2 rounded-xl border bg-card p-6">
    <h3 className="text-2xl font-bold">Main Feature</h3>
  </div>

  {/* Regular items */}
  <div className="rounded-xl border bg-card p-6">
    <h3 className="font-semibold">Feature 2</h3>
  </div>

  <div className="rounded-xl border bg-card p-6">
    <h3 className="font-semibold">Feature 3</h3>
  </div>

  {/* Wide item - spans 2 columns */}
  <div className="md:col-span-2 rounded-xl border bg-card p-6">
    <h3 className="font-semibold">Wide Feature</h3>
  </div>
</div>
フォームのレイアウト
<form className="space-y-6">
  <div className="grid gap-4 sm:grid-cols-2">
    <div className="space-y-2">
      <Label htmlFor="firstName">First name</Label>
      <Input id="firstName" placeholder="John" />
    </div>
    <div className="space-y-2">
      <Label htmlFor="lastName">Last name</Label>
      <Input id="lastName" placeholder="Doe" />
    </div>
  </div>

  <div className="space-y-2">
    <Label htmlFor="email">Email</Label>
    <Input id="email" type="email" placeholder="[email protected]" />
    <p className="text-sm text-muted-foreground">
      We&apos;ll never share your email.
    </p>
  </div>

  <Button type="submit" className="w-full sm:w-auto">
    Submit
  </Button>
</form>
ナビゲーション
<header className="sticky top-0 z-50 w-full border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
  <div className="mx-auto flex h-16 max-w-7xl items-center justify-between px-4 sm:px-6 lg:px-8">
    <Link href="/" className="flex items-center gap-2">
      <Logo className="h-8 w-8" />
      <span className="font-bold">Brand</span>
    </Link>

    <nav className="hidden items-center gap-6 md:flex">
      <Link href="/features" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground">
        Features
      </Link>
      <Link href="/pricing" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground">
        Pricing
      </Link>
    </nav>

    <div className="flex items-center gap-4">
      <Button variant="ghost" size="sm" className="hidden sm:flex">
        Sign in
      </Button>
      <Button size="sm">Get Started</Button>
    </div>
  </div>
</header>

避けるべきアンチパターン

色の間違い
// ❌ Too many colors
className="bg-purple-500 text-pink-400 border-blue-300 shadow-green-200"

// ❌ Direct colors instead of tokens
className="bg-white text-black"

// ❌ Purple/violet as primary (unless explicitly requested)
className="bg-violet-600"

// ❌ Clashing temperature gradients
className="bg-gradient-to-r from-pink-500 to-green-500"

// ✅ Semantic tokens
className="bg-background text-foreground"
タイポグラフィの間違い
// ❌ Too many fonts
<h1 className="font-display">
<p className="font-body">
<span className="font-accent">
<code className="font-mono">   // 4 fonts!

// ❌ Tiny text
className="text-xs"  // Avoid for body text

// ❌ No line-height consideration
className="text-base"  // Missing leading-*

// ✅ Proper typography
className="text-base leading-relaxed"
レイアウトの間違い
// ❌ Desktop-first responsive
className="w-1/3 sm:w-1/2 xs:w-full"

// ❌ Using space-* utilities
className="space-y-4"

// ❌ Floats
className="float-left"

// ❌ Mixing gap and margin
className="flex gap-4 mb-4"

// ✅ Mobile-first with gap
className="flex flex-col gap-4 md:flex-row"
コンポーネントの間違い
// ❌ Monolithic page files (500+ lines)
// ❌ Hardcoded values instead of props
// ❌ Inline styles
// ❌ Non-semantic HTML (div for everything)
// ❌ Missing key props in lists
// ❌ Fetching in useEffect

// ✅ Split into components
// ✅ Use props for customization
// ✅ Tailwind classes
// ✅ Semantic HTML
// ✅ Proper key props
// ✅ Server Components or SWR
アクセシビリティの間違い
// ❌ Click handler on div
<div onClick={handleClick}>Click me</div>

// ❌ Missing alt text
<img src="/photo.jpg" />

// ❌ Color-only indication
<span className="text-red-500">Error</span>

// ❌ Missing focus states
<button className="hover:bg-accent">

// ✅ Use button element
<button onClick={handleClick}>Click me</button>

// ✅ Descriptive alt text
<img src="/photo.jpg" alt="Team meeting in conference room" />

// ✅ Icon + color for errors
<span className="flex items-center gap-2 text-destructive">
  <AlertCircle className="h-4 w-4" />
  Error message
</span>

// ✅ Focus states
<button className="hover:bg-accent focus:ring-2 focus:ring-ring">
視覚面の間違い
// ❌ Abstract decorative shapes
<div className="absolute -top-20 -right-20 h-40 w-40 rounded-full bg-gradient-to-r from-purple-400 to-pink-400 blur-3xl" />

// ❌ Placeholder images left in production
<img src="/placeholder.jpg" />

// ❌ Emojis as icons
<span>📧 Email</span>

// ❌ Hand-drawn SVG maps
<svg><path d="M100,200 L300,400..." /></svg>

// ✅ Real images or GenerateImage tool
// ✅ Proper icon libraries (Lucide, etc.)
// ✅ Mapping libraries for geographic data

クイックリファレンスチェックリスト

リリース前に、次の項目を確認してください。

  • 色: 最大3〜5色、セマンティックトークンを使用
  • タイポグラフィ: フォントは最大2種類、適切な階層を設定
  • 余白: 一貫性を保ち、Tailwindのスケールを使用
  • モバイル: 幅375pxで適切に表示
  • アクセシビリティ: キーボード操作、フォーカス状態、代替テキスト
  • パフォーマンス: 画像を最適化し、コードを分割
  • コンポーネント: 論理的に分割し、モノリシックにしない
  • 読み込み: 非同期コンテンツにはスケルトン状態を用意
  • 空の状態: データがない場合に役立つメッセージを表示
  • エラー: 明確なエラーメッセージと復旧手段を用意
  • インタラクション: ホバー、フォーカス、アクティブ状態を定義

概要

v0 のアプローチは、次のように要約できます。

控えめなエレガンスと、目的に沿ったインタラクション。

すべてのデザイン上の判断は、次の基準を満たす必要があります。

  1. 明瞭さを高めるものですか?
  2. 一貫性を保つものですか?
  3. ユーザーの目的に役立つものですか?
  4. 取り除くとデザインが損なわれますか?

4 つすべてに「はい」と答えられない場合は、その選択を見直してください。

コメント