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.
Scanned 9/7/2026
Install to Claude Code
npx -y skills add ThamJiaHe/claude-code-handbook --skill examples --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Examples?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/thamjiahe-examples-6860293e)More formats (shields.io, HTML) on the badges page.
---
name: "Tailwind CSS Design System"
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."
allowed-tools: Read, Write, Edit
version: 1.1.0
compatibility: Claude Opus 4.5, Claude Code v2.x
updated: 2026-01-24
---
# Tailwind CSS Design System
Systematic Tailwind CSS usage with component patterns, design tokens, and shadcn/ui integration.
## Overview
This Skill enforces:
- Utility-first CSS with Tailwind
- Design tokens and custom configuration
- Component composition patterns
- shadcn/ui integration
- Responsive design (mobile-first)
- Dark mode support
- Performance optimization
Apply when styling components, building design systems, or implementing responsive layouts.
## Tailwind Configuration
### Custom Design Tokens
```ts
// 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;
```
## Component Patterns
### Button Component
```tsx
// 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>
);
}
// Usage
<Button variant="default" size="md">Submit</Button>
<Button variant="outline" size="sm">Cancel</Button>
<Button variant="danger" loading>Delete</Button>
```
### Card Component
```tsx
// 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>
);
}
// Usage
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
<p>Content goes here</p>
</CardContent>
</Card>
```
## Responsive Design (Mobile-First)
```tsx
// ✅ GOOD: Mobile-first responsive design
<div className="
flex flex-col // Mobile: stack vertically
md:flex-row // Tablet: horizontal layout
lg:gap-8 // Desktop: larger spacing
">
<aside className="
w-full // Mobile: full width
md:w-64 // Tablet: fixed sidebar width
">
Sidebar
</aside>
<main className="
w-full // Mobile: full width
md:flex-1 // Tablet+: flexible main content
">
Content
</main>
</div>
// ✅ GOOD: Responsive typography
<h1 className="
text-2xl // Mobile: smaller
md:text-3xl // Tablet: medium
lg:text-4xl // Desktop: larger
font-bold
">
Heading
</h1>
// ✅ GOOD: Responsive padding
<section className="
p-4 // Mobile: smaller padding
md:p-6 // Tablet: medium padding
lg:p-8 // Desktop: larger padding
">
Content
</section>
```
## Dark Mode Support
```tsx
// tailwind.config.ts
module.exports = {
darkMode: 'class', // Use class-based dark mode
// ...
};
// Usage
<div className="
bg-white // Light mode
dark:bg-gray-900 // Dark mode
text-gray-900
dark:text-white
">
Content
</div>
// Toggle dark mode
'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>
);
}
```
## Glassmorphism Pattern
```tsx
<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)'
}
```
## Form Components
```tsx
// 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>
);
}
// Usage
<Input placeholder="Email" error={errors.email} />
```
## Layout Patterns
### Container
```tsx
<div className="container mx-auto px-4 md:px-6 lg:px-8 max-w-7xl">
Content
</div>
```
### Grid
```tsx
<div className="
grid
grid-cols-1 // Mobile: 1 column
md:grid-cols-2 // Tablet: 2 columns
lg:grid-cols-3 // Desktop: 3 columns
gap-4
">
<div>Item 1</div>
<div>Item 2</div>
<div>Item 3</div>
</div>
```
### Flexbox
```tsx
<div className="flex items-center justify-between">
<span>Left</span>
<span>Right</span>
</div>
```
## Performance Optimization
### Purge Unused Classes
```ts
// tailwind.config.ts
module.exports = {
content: [
'./app/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}'
],
// Tailwind automatically purges unused classes in production
};
```
### Use @layer for Custom CSS
```css
/* app/globals.css */
@layer components {
.btn-primary {
@apply bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700;
}
}
```
## Anti-Patterns
```tsx
// ❌ BAD: Inline styles instead of Tailwind
<div style={{ backgroundColor: 'blue', padding: '16px' }}>
Content
</div>
// ✅ GOOD: Use Tailwind classes
<div className="bg-blue-500 p-4">
Content
</div>
// ❌ BAD: Magic numbers
<div className="mt-[23px] w-[347px]">
Content
</div>
// ✅ GOOD: Use spacing scale
<div className="mt-6 w-80">
Content
</div>
// ❌ BAD: Non-responsive
<div className="w-96 p-8">
Content
</div>
// ✅ GOOD: Responsive
<div className="w-full md:w-96 p-4 md:p-8">
Content
</div>
// ❌ BAD: Desktop-first
<div className="lg:flex-row flex-col">
Content
</div>
// ✅ GOOD: Mobile-first
<div className="flex-col lg:flex-row">
Content
</div>
```
## Utility Function
```ts
// lib/utils.ts
import { clsx, type ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// Usage: Merge classes safely
<div className={cn('bg-blue-500', className)}>
Content
</div>
```
## Verification Before Production
- [ ] Tailwind configured with custom tokens
- [ ] Mobile-first responsive design
- [ ] Component variants defined with CVA
- [ ] Dark mode support implemented
- [ ] Forms accessible with labels
- [ ] Performance optimized (purge enabled)
- [ ] No inline styles (use Tailwind)
- [ ] Consistent spacing scale used
- [ ] Color contrast meets WCAG AA
- [ ] Custom utilities documented
## Integration with Project Standards
Enforces design consistency:
- U-1: WCAG 2.1 AA compliant (color contrast)
- Responsive design patterns
- Component reusability
- Performance optimization
## Resources
- Tailwind CSS Docs: https://tailwindcss.com/docs
- shadcn/ui: https://ui.shadcn.com
- CVA (Class Variance Authority): https://cva.style
---
**Last Updated:** January 24, 2026
**Compatibility:** Claude Opus 4.5, Claude Code v2.x
**Status:** Production Ready
> **January 2026 Update:** This skill is compatible with Claude Opus 4.5 and Claude Code v2.x. For complex tasks, use the `effort: high` parameter for thorough analysis.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!