インターフェースのインタラクション
UI コンポーネント設計、インタラクションパターン、レスポンシブデザイン、ユーザーエクスペリエンス原則を習得し、優れたユーザーインターフェースを構築する。
Sequential Thinking を使って、AI駆動のインタラクションデザインを学ぶ
AI によるインターフェースインタラクションへの応用は複数の層面に関わり、使用構造化思考の方法次の内容を体系的に習得するのに役立ちます:
デザインシステム(Design System)
デザインシステムは、再利用可能なデザイン標準とコンポーネントライブラリのセットであり、製品の一貫性と保守性を確保します。
Design Tokens 設計トークン
Design Tokens はデザイン判断の最小単位であり、CSS 変数を通じて色、余白、フォントなどのデザイン要素を一元管理します。
カラ―システム(OKLCH カラースペース)
OKLCH 色空間を使用すると、色のコントラストとテーマ切り替えをより適切に処理できます。プロジェクト内の色定義:
:root {
--primary: oklch(0.7 0.15 200);
--background: oklch(0.09 0 0);
--foreground: oklch(0.98 0 0);
--border: oklch(0.25 0 0);
/* ... その他のカラーバリアブル */
}スペーシングシステム
Tailwind のデフォルト間隔比率(4px 基準):0, 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40, 48, 56, 64
フォントシステム
角丸システム
テーマシステム
ダークモードの実装
使用 next-themes テーマ切り替えを実装する:
// app/layout.tsx
import { ThemeProvider } from '@/components/theme-provider'
export default function RootLayout({ children }) {
return (
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
)
}CSS 変数によるテーマ切り替え
合格 .dark クラス切り替えテーマ変数:
.dark {
--background: oklch(0.09 0 0);
--foreground: oklch(0.98 0 0);
/* 暗色モード下のすべてのカラーバリアブル */
}コンポーネントアーキテクチャ
アトミックデザイン方法論
コンポーネントバリアントシステム(CVA)
使用 class-variance-authority コンポーネントのバリエーションを管理する:
import { cva, type VariantProps } from 'class-variance-authority'
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md',
{
variants: {
variant: {
default: 'bg-primary text-primary-foreground',
destructive: 'bg-destructive text-destructive-foreground',
outline: 'border border-input',
},
size: {
default: 'h-10 px-4 py-2',
sm: 'h-9 rounded-md px-3',
lg: 'h-11 rounded-md px-8',
},
},
defaultVariants: {
variant: 'default',
size: 'default',
},
}
)AI によるインターフェース対話のベストプラクティス
AI を活用してフロントエンド UI 開発の効率を向上させる、コンポーネント設計からパフォーマンス最適化までの全工程にわたる AI 支援の実践。
AI 支援コンポーネント開発
AI を使ってコンポーネントコードを生成する
AI にコンポーネント要件を伝えると、完全な React/Next.js コンポーネントを生成してくれる:
Prompt テンプレート: ユーザーカードコンポーネントを作成する必要があります。以下の機能を含めてください。 1. ユーザーのアバター、名前、メールアドレスを表示する 2. クリックして詳細を表示できる 3. Tailwind CSS スタイルを使用する 4. ダークモードをサポートする 5. レスポンシブデザイン(モバイル端末とデスクトップ端末) 6. TypeScript を使用する 7. shadcn/ui のデザイン規約に従う 完全なコンポーネントコードを生成してください。以下を含めてください。 - 型定義 - Props インターフェース - スタイルクラス名 - レスポンシブブレークポイント - アクセシビリティ属性
AI 生成のコンポーネント例
// components/user-card.tsx
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
import { Card, CardContent } from '@/components/ui/card'
interface UserCardProps {
name: string
email: string
avatar?: string
onClick?: () => void
}
export function UserCard({ name, email, avatar, onClick }: UserCardProps) {
const initials = name
.split(' ')
.map(n => n[0])
.join('')
.toUpperCase()
.slice(0, 2)
return (
<Card
className="cursor-pointer transition-shadow hover:shadow-md"
onClick={onClick}
role="button"
tabIndex={0}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
onClick?.()
}
}}
>
<CardContent className="p-4 flex items-center gap-4">
<Avatar className="h-12 w-12">
<AvatarImage src={avatar} alt={name} />
<AvatarFallback>{initials}</AvatarFallback>
</Avatar>
<div className="flex-1 min-w-0">
<h3 className="font-semibold text-foreground truncate">{name}</h3>
<p className="text-sm text-muted-foreground truncate">{email}</p>
</div>
</CardContent>
</Card>
)
}AIによるスタイル最適化支援
AI を使用して Tailwind CSS のクラス名を最適化し、より簡潔で効率的なスタイルを生成します:
Prompt: 以下の Tailwind CSS クラス名をより簡潔で効率的になるように最適化してください: 現在のコード: <div className="flex flex-row items-center justify-between p-4 m-2 bg-white dark:bg-gray-800 rounded-lg shadow-sm hover:shadow-md transition-shadow duration-200"> お願いします: 1. 重複するクラス名を統合する 2. より簡潔な書き方を使う 3. レスポンシブ対応とダークモード対応を確保する 4. 同じ視覚効果を維持する
AI 支援コンポーネントライブラリの選定
Prompt: Next.js 16 + TypeScript プロジェクト向けにコンポーネントライブラリを選びたいです。要件は以下のとおりです。 1. ダークモード対応 2. 高いカスタマイズ性 3. 型安全 4. 優れたパフォーマンス 5. 活発なコミュニティ 以下のコンポーネントライブラリを比較してください。 - shadcn/ui - Material-UI (MUI) - Ant Design - Chakra UI 推奨と理由を示し、Next.js プロジェクトにどのように統合するかも説明してください。
UI コンポーネント設計
コンポーネント化は現代のフロントエンド開発の中核的な考え方であり、再利用可能なコンポーネントを組み合わせて複雑なユーザーインターフェースを構築します。
Tailwind CSS の詳細設定
構成ファイルの構造
// tailwind.config.ts
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
colors: {
background: 'var(--background)',
foreground: 'var(--foreground)',
// CSS 変数を使用
},
borderRadius: {
lg: 'var(--radius)',
md: 'calc(var(--radius) - 2px)',
sm: 'calc(var(--radius) - 4px)',
},
},
},
plugins: [],
}
export default configカスタムツールクラス
// globals.css にカスタムユーティリティクラスを追加
@layer utilities {
.text-balance {
text-wrap: balance;
}
.scrollbar-hide {
-ms-overflow-style: none;
scrollbar-width: none;
}
.scrollbar-hide::-webkit-scrollbar {
display: none;
}
}レスポンシブブレークポイントのカスタマイズ
// tailwind.config.ts
theme: {
screens: {
'xs': '475px',
'sm': '640px',
'md': '768px',
'lg': '1024px',
'xl': '1280px',
'2xl': '1536px',
},
}ダークモード設定
使用 dark: プレフィックス:
<div className="bg-white dark:bg-gray-900 text-gray-900 dark:text-white">
{/* コンテンツ */}
</div>コンポーネントライブラリの比較と選定
| コンポーネントライブラリ | 特徴 | 適用シーン |
|---|---|---|
| shadcn/ui | コピー&ペースト可能、完全に制御可能、Radix UI ベース | 高度にカスタマイズされたプロジェクト、Next.jsプロジェクト |
| Material-UI | 豊富なコンポーネント、充実したドキュメント、Material Design | エンタープライズアプリケーション、迅速なプロトタイピング |
| Ant Design | エンタープライズ向けコンポーネント、管理画面アプリケーション、中国語ドキュメント | 中台システム、管理プラットフォーム |
| Chakra UI | シンプル、モジュール化、TypeScript 対応 | 現代の Web アプリケーション、柔軟性が必要なプロジェクト |
インタラクティブモード
優れたインタラクションデザインは、ユーザー操作をよりスムーズで直感的にします。状態管理、フォーム処理、アニメーションのテクニックを身につけましょう。
ステート管理の詳細ガイド
useState のベストプラクティス
// 関数型更新を使用してクロージャの問題を回避 const [count, setCount] = useState(0) // 正しい: 関数型更新を使用 setCount(prev => prev + 1) // 避ける: state に直接依存する setCount(count + 1) // 正確ではない可能性がある // 複雑な状態には useReducer を使用 const [state, dispatch] = useReducer(reducer, initialState)
フォーム処理のベストプラクティス
フォーム検証の例
// 完全なフォームコンポーネントの例
'use client'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@/components/ui/form'
const formSchema = z.object({
username: z.string().min(2, 'ユーザー名は2文字以上である必要があります'),
email: z.string().email('無効なメールアドレス'),
})
export function UserForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
username: '',
email: '',
},
})
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="username"
render={({ field }) => (
<FormItem>
<FormLabel>ユーザー名</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit">送信</Button>
</form>
</Form>
)
}フォーム性能の最適化
- 使用
mode: 'onBlur'検証回数を減らす - 複雑なフォームの使用
useFieldArray動的フィールドの管理 - 大規模フォームの使用
shouldUnregisterメモリを最適化する
ユーザーフィードバックシステム
トースト通知
import { toast } from 'sonner'
toast.success('操作に成功しました')
toast.error('操作に失敗しました')
toast.info('お知らせ')Loading 状態
// Skeletonの読み込み <Skeleton className="h-4 w-[250px]" /> // Spinner <Loader2 className="h-4 w-4 animate-spin" />
アニメーションとトランジション
Tailwind アニメーション
// tailwindcss-animate を使用
<div className="animate-in fade-in slide-in-from-top-4">
{/* 内容 */}
</div>
// よく使うアニメーションクラス
animate-in // प्रवेशアニメーション
animate-out // 退出アニメーション
fade-in // フェードイン
slide-in-from-top // 上からスライドイン
duration-300 // 継続時間パフォーマンスの考慮事項
- 使用
transformとopacityGPU アクセラレーションを有効にする - アニメーションを避ける
width、heightなどの属性 - 使用
will-changeブラウザ最適化のヒント
レスポンシブデザイン
さまざまなデバイスで優れたユーザー体験を提供できるよう、インターフェースを保証する。モバイルファースト戦略を採用し、柔軟なレイアウト技術を使用する。
モバイルファースト戦略
モバイルデザイン原則
- まずモバイル向けに設計し、その後段階的にデスクトップ体験を強化する
- モバイル端末の操作を簡素化し、操作手順を減らす
- タッチターゲットのサイズを最適化する(最小 44x44px)
- モバイル端末向けコンテンツを減らし、コア機能を強調する
モバイルナビゲーションパターン
レイアウト技術
Flexbox の高度な使い方
// レスポンシブ Flexbox
<div className="flex flex-col md:flex-row gap-4">
<div className="flex-1">内容 1</div>
<div className="flex-1">内容 2</div>
</div>
// 配置方法
<div className="flex items-center justify-between">
{/* 垂直方向中央揃え、水平両端揃え */}
</div>中断戦略
// ブレークポイントのベストプラクティス
// モバイルファースト:デフォルトのスタイルはモバイル向け
<div className="text-sm md:text-base lg:text-lg">
{/* 小さい画面から大きい画面へ段階的に強化 */}
</div>
// 避ける:デスクトップファースト(推奨しない)
<div className="text-lg md:text-base sm:text-sm">
{/* これはモバイル端末の負担を増やします */}
</div>モバイル端末の最適化
ビューポート設定
// app/layout.tsx
export const metadata = {
viewport: {
width: 'device-width',
initialScale: 1,
maximumScale: 5,
},
}タッチイベント処理
- 使用
touch-actionタッチ応答の最適化 - 回避する
hoverモバイル端末での誤タップによる状態 - 使用
@media (hover: hover)デバイスがホバーをサポートしているかを検出する
アクセシビリティ(Accessibility)
アクセシビリティにより、支援技術を使用するユーザーを含むすべてのユーザーがあなたのアプリを利用できるようになります。WCAG 標準に従い、製品をより包括的にしましょう。
WCAG 標準
WCAG 2.1 レベル
重要な原則(POUR)
キーボードナビゲーション
Tab 順序管理
// Tab 順序を tabIndex で制御する
<button tabIndex={1}>最初</button>
<button tabIndex={2}>2番目</button>
// 互換性のない要素をスキップする
<div tabIndex={-1}>この要素をスキップする</div>
// Tab 順序から外す(推奨しません。必要な場合のみ)
<button tabIndex={-1}>Tab でアクセス不可</button>フォーカス管理
// フォーカストラップ(Focus Trap)- モーダル内で使用
import { FocusTrap } from '@radix-ui/react-focus-trap'
<FocusTrap>
<Dialog>
{/* フォーカスはダイアログ内に制限される */}
</Dialog>
</FocusTrap>
// フォーカス可視スタイル
<button className="focus-visible:ring-2 focus-visible:ring-primary">
{/* キーボード操作時にフォーカスリングを表示 */}
</button>ショートカットキー対応
- Enter/Space:ボタンまたはリンクを有効化する
- Esc:モーダルダイアログまたはメニューを閉じる
- Arrow Keys:リストまたはメニュー項目をナビゲート
- Tab:フォーカス可能な要素間を移動する
スクリーンリーダー対応
ARIA ラベルの使用
// aria-label:要素にラベルを付与する
<button aria-label="ダイアログを閉じる">
<X />
</button>
// aria-labelledby:他の要素の ID を参照する
<div aria-labelledby="dialog-title">
<h2 id="dialog-title">ダイアログのタイトル</h2>
</div>
// aria-describedby:追加の説明を提供する
<input
aria-describedby="email-help"
aria-invalid={hasError}
/>
<span id="email-help">有効なメールアドレスを入力してください</span>セマンティックHTML
// セマンティックタグを使用する
<nav>ナビゲーション</nav>
<main>メインコンテンツ</main>
<article>記事</article>
<section>セクション</section>
<aside>サイドバー</aside>
<header>ヘッダー</header>
<footer>フッター</footer>
// 避ける:セマンティックタグの代わりに div を使用する
<div className="nav"> {/* 非推奨 */}
<nav> {/* 推奨 */}役割定義
// role 属性を使用する(セマンティックなタグが使用できない場合)
<div role="button" tabIndex={0} onClick={handleClick}>
カスタムボタン
</div>
<div role="alert" aria-live="polite">
重要なお知らせ
</div>
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
{/* モーダルダイアログ */}
</div>色のコントラスト
WCAG AA基準
ツールチェック
- WebAIM Contrast Checker:オンラインコントラストチェックツール
- Lighthouse:Chrome DevTools に組み込まれた監査
- axe DevTools:ブラウザー拡張機能
色に頼って情報を伝えない
// エラー:状態を色だけで表す <span className="text-red-500">エラー</span> // 正解:色 + アイコン/テキスト <span className="text-red-500 flex items-center gap-1"> <AlertCircle /> エラー:有効な値を入力してください </span>
アクセシビリティテスト
自動化テストツール
手動テストのフロー
- キーボードのみでアプリ全体を操作する
- スクリーンリーダー(NVDA、JAWS、VoiceOver)を使用してテストする
- 色のコントラストを確認する
- すべての画像に alt テキストがあることを確認する
- テストフォームのエラーメッセージ
キーボードテストチェックリスト
- すべてのインタラクティブ要素はTabでアクセスできます
- フォーカス順序のロジックが合理的
- フォーカスが見える(フォーカスリングあり)
- モーダルは Esc で閉じられる
- メニューは矢印キーで操作できます
パフォーマンス最適化
パフォーマンスはユーザー体験に直接影響します。描画パフォーマンス、リソース読み込み、実行時パフォーマンスを最適化し、アプリの高速な応答を確保します。
レンダリング性能
React レンダリング最適化
// memo を使用して不要な再レンダリングを回避
const ExpensiveComponent = React.memo(({ data }) => {
return <div>{/* 複雑なレンダリング */}</div>
})
// useMemo を使用して計算結果をキャッシュ
const expensiveValue = useMemo(() => {
return computeExpensiveValue(a, b)
}, [a, b])
// useCallback を使用して関数をキャッシュ
const handleClick = useCallback(() => {
doSomething(id)
}, [id])仮想スクロール
大量のリストでは、仮想スクロールを使用して表示中の項目のみをレンダリングします:
// react-window または react-virtualized を使用
import { FixedSizeList } from 'react-window'
<FixedSizeList
height={600}
itemCount={10000}
itemSize={50}
width="100%"
>
{Row}
</FixedSizeList>コード分割
// コンポーネントを動的にインポート
import dynamic from 'next/dynamic'
const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
loading: () => <Skeleton />,
ssr: false, // SSR を無効にする必要がある場合
})
// ルートレベルのコード分割(Next.js が自動処理)
// app/dashboard/page.tsx は自動的に分割されるリソース最適化
画像最適化
// Next.js Image コンポーネントによる自動最適化
import Image from 'next/image'
<Image
src="/hero.jpg"
alt="Hero"
width={1200}
height={600}
priority // ファーストビューの画像
loading="lazy" // ファーストビュー以外の画像
placeholder="blur" // ぼかしプレースホルダー
/>
// WebP、AVIF などの最新フォーマットをサポート
// レスポンシブ画像を自動生成フォント最適化
// Use next/font to optimize fonts
import { GeistSans } from 'next/font/google'
const geistSans = GeistSans({
subsets: ['latin'],
display: 'swap', // Font loading strategy
preload: true,
})
// Font subsetting, load only the required charactersリソースの事前読み込み
// サードパーティドメインを事前接続 <link rel="preconnect" href="https://fonts.googleapis.com" /> // 重要リソースを事前読み込み <link rel="preload" href="/fonts/geist.woff2" as="font" /> // 次のページのリソースを事前取得 <link rel="prefetch" href="/dashboard" />
実行時パフォーマンス
Bundleサイズの最適化
- 使用
bundle analyzerバンドルサイズを分析する - 必要に応じてライブラリを導入(
import { debounce } from 'lodash-es') - 未使用の依存関係を削除
Tree Shaking
Next.js と最新のビルドツールは Tree Shaking を自動的に実行し、未使用のコードを削除します。
パフォーマンス監視
Core Web Vitals
パフォーマンス分析ツール
- React DevTools Profiler:コンポーネントのレンダリング性能を分析する
- Lighthouse:Chrome DevTools のパフォーマンス監査
- Web Vitals Extension:Core Web Vitals をリアルタイムで監視
実践例
実際のコード例を通して、高品質な UI コンポーネントとインタラクションの構築方法を学びます。
完全なフォームコンポーネントの例
'use client'
import { useForm } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
import { z } from 'zod'
import { Button } from '@/components/ui/button'
import { Input } from '@/components/ui/input'
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from '@/components/ui/form'
import { toast } from 'sonner'
const formSchema = z.object({
name: z.string().min(2, '名前は2文字以上である必要があります'),
email: z.string().email('無効なメールアドレスです'),
age: z.number().min(18, '年齢は18より大きくなければなりません').max(100),
})
export function UserForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
name: '',
email: '',
age: 18,
},
})
async function onSubmit(values: z.infer<typeof formSchema>) {
try {
await saveUser(values)
toast.success('ユーザーの作成に成功しました')
form.reset()
} catch (error) {
toast.error('作成に失敗しました。再試行してください')
}
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
<FormField
control={form.control}
name="name"
render={({ field }) => (
<FormItem>
<FormLabel>名前</FormLabel>
<FormControl>
<Input placeholder="名前を入力してください" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<Button type="submit" disabled={form.formState.isSubmitting}>
{form.formState.isSubmitting ? '送信中...' : '送信'}
</Button>
</form>
</Form>
)
}学習成果
この章を終えると、あなたは:
- 1デザインシステムの基礎を理解し、Design Tokens、テーマシステム、コンポーネントアーキテクチャを習得する
- 2Tailwind CSS と shadcn/ui を使いこなし、コンポーネントライブラリを設定およびカスタマイズできる
- 3状態管理、フォーム処理、アニメーションのテクニックを習得し、滑らかなインタラクション体験を構築する
- 4レスポンシブデザインの方法を習得し、モバイルファースト戦略と最新のレイアウト技術を使用する
- 5アクセシビリティ標準(WCAG)を理解し、キーボードナビゲーションとスクリーンリーダーのサポートを実装できる
- 6レンダリング最適化、リソース読み込み、パフォーマンス監視を含むパフォーマンス最適化のテクニックを習得する
- 7完全なフォームコンポーネント、レスポンシブレイアウト、インタラクティブ機能を構築できる