Tailwind CSS Design System
Tailwind CSS、shadcn/ui、カスタムデザイントークンを使用して、一貫性のあるアクセシブルなUIコンポーネントを構築できます。コンポーネントのスタイリング、デザインシステムの構築、レスポンシブレイアウトの実装、CSSパフォーマンスの最適化の際に活用してください。
description の原文を見る
Build consistent, accessible UI components with Tailwind CSS, shadcn/ui, and custom design tokens. Apply when styling components, creating design systems, implementing responsive layouts, or optimizing CSS performance.
SKILL.md 本文
Tailwind CSS デザインシステム
コンポーネントパターン、デザイントークン、shadcn/ui統合を用いた体系的なTailwind CSSの使用方法。
概要
このスキルが強制する内容:
- Tailwindを使用したユーティリティファーストのCSS
- デザイントークンとカスタム設定
- コンポーネント構成パターン
- shadcn/ui統合
- レスポンシブデザイン(モバイルファースト)
- ダークモードサポート
- パフォーマンス最適化
コンポーネントのスタイリング、デザインシステムの構築、またはレスポンシブレイアウトの実装時に適用します。
Tailwind設定
カスタムデザイントークン
// tailwind.config.ts
import type { Config } from 'tailwindcss';
const config: Config = {
content: [
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}'
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
500: '#3b82f6',
600: '#2563eb',
900: '#1e3a8a'
},
secondary: {
500: '#8b5cf6',
600: '#7c3aed'
}
},
spacing: {
'18': '4.5rem',
'22': '5.5rem'
},
fontSize: {
'xs': '0.75rem',
'sm': '0.875rem',
'base': '1rem',
'lg': '1.125rem',
'xl': '1.25rem',
'2xl': '1.5rem'
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace']
},
borderRadius: {
'none': '0',
'sm': '0.125rem',
DEFAULT: '0.25rem',
'md': '0.375rem',
'lg': '0.5rem',
'xl': '0.75rem',
'full': '9999px'
},
boxShadow: {
'sm': '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1)',
'md': '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
'lg': '0 10px 15px -3px rgba(0, 0, 0, 0.1)',
'xl': '0 20px 25px -5px rgba(0, 0, 0, 0.1)',
'glass': '0 8px 32px 0 rgba(31, 38, 135, 0.37)'
}
}
},
plugins: [
require('@tailwindcss/forms'),
require('@tailwindcss/typography')
]
};
export default config;
コンポーネントパターン
Buttonコンポーネント
// components/ui/Button.tsx
import { cva, type VariantProps } from 'class-variance-authority';
import { cn } from '@/lib/utils';
const buttonVariants = cva(
'inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50',
{
variants: {
variant: {
default: 'bg-primary-600 text-white hover:bg-primary-700',
secondary: 'bg-secondary-500 text-white hover:bg-secondary-600',
outline: 'border border-gray-300 bg-transparent hover:bg-gray-100',
ghost: 'hover:bg-gray-100',
danger: 'bg-red-600 text-white hover:bg-red-700'
},
size: {
sm: 'h-9 px-3 text-sm',
md: 'h-10 px-4 text-base',
lg: 'h-11 px-8 text-lg',
icon: 'h-10 w-10'
}
},
defaultVariants: {
variant: 'default',
size: 'md'
}
}
);
interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
loading?: boolean;
}
export function Button({
className,
variant,
size,
loading,
disabled,
children,
...props
}: ButtonProps) {
return (
<button
className={cn(buttonVariants({ variant, size, className }))}
disabled={disabled || loading}
{...props}
>
{loading && <span className="mr-2">Loading...</span>}
{children}
</button>
);
}
// 使用例
<Button variant="default" size="md">Submit</Button>
<Button variant="outline" size="sm">Cancel</Button>
<Button variant="danger" loading>Delete</Button>
Cardコンポーネント
// components/ui/Card.tsx
import { cn } from '@/lib/utils';
interface CardProps extends React.HTMLAttributes<HTMLDivElement> {}
export function Card({ className, children, ...props }: CardProps) {
return (
<div
className={cn(
'rounded-lg border border-gray-200 bg-white p-6 shadow-sm',
className
)}
{...props}
>
{children}
</div>
);
}
export function CardHeader({ className, children, ...props }: CardProps) {
return (
<div className={cn('mb-4', className)} {...props}>
{children}
</div>
);
}
export function CardTitle({ className, children, ...props }: CardProps) {
return (
<h3 className={cn('text-2xl font-semibold', className)} {...props}>
{children}
</h3>
);
}
export function CardContent({ className, children, ...props }: CardProps) {
return (
<div className={cn('', className)} {...props}>
{children}
</div>
);
}
// 使用例
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
<p>Content goes here</p>
</CardContent>
</Card>
レスポンシブデザイン(モバイルファースト)
// ✅ 良い例: モバイルファーストのレスポンシブデザイン
<div className="
flex flex-col // モバイル: 垂直に積み重ねる
md:flex-row // タブレット: 水平レイアウト
lg:gap-8 // デスクトップ: より大きな間隔
">
<aside className="
w-full // モバイル: 全幅
md:w-64 // タブレット: 固定サイドバー幅
">
Sidebar
</aside>
<main className="
w-full // モバイル: 全幅
md:flex-1 // タブレット以上: 柔軟なメインコンテンツ
">
Content
</main>
</div>
// ✅ 良い例: レスポンシブタイポグラフィ
<h1 className="
text-2xl // モバイル: より小さい
md:text-3xl // タブレット: 中サイズ
lg:text-4xl // デスクトップ: より大きい
font-bold
">
Heading
</h1>
// ✅ 良い例: レスポンシブパディング
<section className="
p-4 // モバイル: より小さいパディング
md:p-6 // タブレット: 中パディング
lg:p-8 // デスクトップ: より大きいパディング
">
Content
</section>
ダークモードサポート
// tailwind.config.ts
module.exports = {
darkMode: 'class', // クラスベースのダークモードを使用
// ...
};
// 使用例
<div className="
bg-white // ライトモード
dark:bg-gray-900 // ダークモード
text-gray-900
dark:text-white
">
Content
</div>
// ダークモードの切り替え
'use client';
import { useEffect, useState } from 'react';
export function ThemeToggle() {
const [theme, setTheme] = useState('light');
useEffect(() => {
const root = document.documentElement;
root.classList.remove('light', 'dark');
root.classList.add(theme);
localStorage.setItem('theme', theme);
}, [theme]);
return (
<button
onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
className="p-2 rounded-md bg-gray-200 dark:bg-gray-700"
>
{theme === 'light' ? '🌙' : '☀️'}
</button>
);
}
グラスモーフィズムパターン
<div className="
relative
rounded-xl
bg-white/10
backdrop-blur-lg
border border-white/20
shadow-glass
p-6
">
Glass card content
</div>
// tailwind.config.ts
boxShadow: {
'glass': '0 8px 32px 0 rgba(31, 38, 135, 0.37)'
}
フォームコンポーネント
// components/ui/Input.tsx
import { cn } from '@/lib/utils';
interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
error?: string;
}
export function Input({ className, error, ...props }: InputProps) {
return (
<div className="w-full">
<input
className={cn(
'w-full rounded-md border border-gray-300 px-3 py-2',
'focus:outline-none focus:ring-2 focus:ring-primary-500',
'disabled:cursor-not-allowed disabled:opacity-50',
error && 'border-red-500 focus:ring-red-500',
className
)}
{...props}
/>
{error && <p className="mt-1 text-sm text-red-600">{error}</p>}
</div>
);
}
// 使用例
<Input placeholder="Email" error={errors.email} />
レイアウトパターン
コンテナ
<div className="container mx-auto px-4 md:px-6 lg:px-8 max-w-7xl">
Content
</div>
グリッド
<div className="
grid
grid-cols-1 // モバイル: 1列
md:grid-cols-2 // タブレット: 2列
lg:grid-cols-3 // デスクトップ: 3列
gap-4
">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
フレックスボックス
<div className="flex items-center justify-between">
<span>Left</span>
<span>Right</span>
</div>
パフォーマンス最適化
未使用クラスの削除
// tailwind.config.ts
module.exports = {
content: [
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}'
],
// Tailwindは本番環境で未使用のクラスを自動的に削除します
};
@layerを使用したカスタムCSS
/* app/globals.css */
@layer components {
.btn-primary {
@apply bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700;
}
}
アンチパターン
// ❌ 悪い例: Tailwindの代わりにインラインスタイルを使用
<div style={{ backgroundColor: 'blue', padding: '16px' }}>
Content
</div>
// ✅ 良い例: Tailwindクラスを使用
<div className="bg-blue-500 p-4">
Content
</div>
// ❌ 悪い例: マジックナンバー
<div className="mt-[23px] w-[347px]">
Content
</div>
// ✅ 良い例: スペーシングスケールを使用
<div className="mt-6 w-80">
Content
</div>
// ❌ 悪い例: レスポンシブでない
<div className="w-96 p-8">
Content
</div>
// ✅ 良い例: レスポンシブ
<div className="w-full md:w-96 p-4 md:p-8">
Content
</div>
// ❌ 悪い例: デスクトップファースト
<div className="lg:flex-row flex-col">
Content
</div>
// ✅ 良い例: モバイルファースト
<div className="flex-col lg:flex-row">
Content
</div>
ユーティリティ関数
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// 使用例: クラスを安全にマージ
<div className={cn('bg-blue-500', className)}>
Content
</div>
本番環境前の検証
- Tailwindはカスタムトークンで設定されている
- モバイルファーストのレスポンシブデザイン
- CVAでコンポーネントバリアントが定義されている
- ダークモードサポートが実装されている
- フォームはラベル付きでアクセス可能
- パフォーマンスが最適化されている(削除が有効)
- インラインスタイルがない(Tailwindを使用)
- 一貫したスペーシングスケールが使用されている
- 色のコントラストがWCAG AA基準を満たしている
- カスタムユーティリティが文書化されている
プロジェクト標準との統合
デザインの一貫性を強制します:
- U-1: WCAG 2.1 AA準拠(色のコントラスト)
- レスポンシブデザインパターン
- コンポーネント再利用性
- パフォーマンス最適化
リソース
- Tailwind CSS ドキュメント: https://tailwindcss.com/docs
- shadcn/ui: https://ui.shadcn.com
- CVA (Class Variance Authority): https://cva.style
最終更新: 2026年1月24日 互換性: Claude Opus 4.5、Claude Code v2.x ステータス: 本番環境対応
2026年1月更新: このスキルはClaude Opus 4.5およびClaude Code v2.xと互換性があります。複雑なタスクの場合は、
effort: highパラメータを使用して詳細な分析を行ってください。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- ThamJiaHe
- ライセンス
- MIT
- 最終更新
- 2026/4/19
Source: https://github.com/ThamJiaHe/claude-code-handbook / ライセンス: MIT