Agent skill
shadcn-ui-designer
Design and build modern UI components and pages using shadcn/ui. Creates clean, accessible interfaces with Tailwind CSS following shadcn principles. Use when building UI components, pages, forms, dashboards, or any interface work.
Install this agent skill to your Project
npx add-skill https://github.com/JSBtechnologies/claude-skills/tree/main/shadcn-ui-designing
SKILL.md
Shadcn UI Designer
Build production-ready UI components using shadcn/ui principles: minimal, accessible, composable, and beautiful by default.
Core Philosophy
Design modern, minimal interfaces with:
- Clean typography (Inter/system fonts, 2-3 weights max)
- Ample whitespace (4px-based spacing: p-1 through p-8)
- Subtle shadows (shadow-sm/md/lg only)
- Accessible contrast (WCAG AA minimum)
- Smooth micro-interactions (200-300ms transitions)
- Professional neutrals (slate/zinc scale) with subtle accents
Build composable components that work together seamlessly.
Quick Start Pattern
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
export function MyComponent() {
return (
<div className="container mx-auto p-6 space-y-6">
<div className="space-y-2">
<h1 className="text-2xl font-semibold">Title</h1>
<p className="text-sm text-muted-foreground">Description</p>
</div>
<Card className="shadow-sm">
<CardHeader>
<CardTitle>Section</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* Content here */}
</CardContent>
</Card>
</div>
)
}
Design System Rules
Typography
- Hierarchy:
text-2xl(headings) →text-base(body) →text-sm(secondary) - Weights:
font-semibold(600) for emphasis,font-medium(500) for labels,font-normal(400) for body - Colors:
text-foreground(primary),text-muted-foreground(secondary)
<h1 className="text-2xl font-semibold">Page Title</h1>
<p className="text-muted-foreground">Supporting text</p>
Spacing
Use consistent spacing scale:
- Micro:
space-y-2(8px) - within sections - Small:
space-y-4(16px) - between elements - Medium:
space-y-6(24px) - between sections - Large:
space-y-8(32px) - major divisions
<div className="container mx-auto p-6 space-y-6">
<section className="space-y-4">
<div className="space-y-2">
{/* Related elements */}
</div>
</section>
</div>
Colors
Use semantic color tokens:
- Background:
bg-background,bg-card,bg-muted - Foreground:
text-foreground,text-muted-foreground - Borders:
border-border,border-input - Primary:
bg-primary,text-primary-foreground - Destructive:
bg-destructive,text-destructive-foreground
<Card className="bg-card text-card-foreground border-border">
<Button className="bg-primary text-primary-foreground">
Primary Action
</Button>
<div className="bg-muted/50 text-muted-foreground">
Subtle highlight
</div>
</Card>
Shadows & Elevation
Three levels only:
shadow-sm: Cards, raised sections (0 1px 2px)shadow-md: Dropdowns, popovers (0 4px 6px)shadow-lg: Modals, dialogs (0 10px 15px)
<Card className="shadow-sm hover:shadow-md transition-shadow" />
Animations
- Duration: 200-300ms
- Easing: ease-in-out
- Use cases: Hover states, loading states, reveals
<Button className="transition-colors duration-200 hover:bg-primary/90">
<Card className="transition-all duration-200 hover:shadow-md hover:scale-[1.02]">
Accessibility
Always include:
- Semantic HTML (
<main>,<nav>,<article>) - ARIA labels on icons/actions
- Focus states (
:focus-visible:ring-2) - Keyboard navigation
- WCAG AA contrast (4.5:1 minimum)
<button
aria-label="Close dialog"
className="focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2"
>
<X className="h-4 w-4" />
</button>
Component Patterns
Dashboard Cards
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-4">
{stats.map(stat => (
<Card key={stat.id} className="shadow-sm">
<CardHeader className="flex flex-row items-center justify-between pb-2">
<CardTitle className="text-sm font-medium">
{stat.label}
</CardTitle>
{stat.icon}
</CardHeader>
<CardContent>
<div className="text-2xl font-bold">{stat.value}</div>
<p className="text-xs text-muted-foreground">
{stat.change}
</p>
</CardContent>
</Card>
))}
</div>
Forms
<form className="space-y-6">
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="name">Full Name</Label>
<Input
id="name"
placeholder="Enter your name"
className="max-w-md"
/>
</div>
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
placeholder="name@example.com"
className="max-w-md"
/>
</div>
</div>
<div className="flex gap-3">
<Button type="submit">Submit</Button>
<Button type="button" variant="outline">Cancel</Button>
</div>
</form>
Data Tables
<Card className="shadow-sm">
<CardHeader>
<CardTitle>Recent Orders</CardTitle>
</CardHeader>
<CardContent>
<Table>
<TableHeader>
<TableRow>
<TableHead>Order</TableHead>
<TableHead>Customer</TableHead>
<TableHead>Status</TableHead>
<TableHead className="text-right">Amount</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{orders.map(order => (
<TableRow
key={order.id}
className="hover:bg-muted/50 transition-colors"
>
<TableCell className="font-medium">{order.id}</TableCell>
<TableCell>{order.customer}</TableCell>
<TableCell>
<Badge variant={order.statusVariant}>
{order.status}
</Badge>
</TableCell>
<TableCell className="text-right">
{order.amount}
</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</CardContent>
</Card>
Modals/Dialogs
<Dialog>
<DialogTrigger asChild>
<Button>Open Dialog</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit Profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when done.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 py-4">
{/* Form fields */}
</div>
<DialogFooter>
<Button type="submit">Save changes</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Loading States
// Skeleton loading
<Card className="shadow-sm">
<CardHeader>
<Skeleton className="h-4 w-[200px]" />
</CardHeader>
<CardContent className="space-y-3">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-[80%]" />
</CardContent>
</Card>
// Loading button
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Please wait
</Button>
Empty States
<Card className="shadow-sm">
<CardContent className="flex flex-col items-center justify-center py-12 space-y-3">
<div className="p-4 bg-muted rounded-full">
<FileX className="h-8 w-8 text-muted-foreground" />
</div>
<div className="text-center space-y-1">
<h3 className="font-semibold">No results found</h3>
<p className="text-sm text-muted-foreground">
Try adjusting your search
</p>
</div>
<Button variant="outline" size="sm">
Clear filters
</Button>
</CardContent>
</Card>
Layout Patterns
Container Widths
// Full width with constraints
<div className="container mx-auto px-4 max-w-7xl">
// Content-focused (prose)
<div className="container mx-auto px-4 max-w-3xl">
// Form-focused
<div className="container mx-auto px-4 max-w-2xl">
Responsive Grids
// Dashboard grid
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
// Content + sidebar
<div className="grid gap-6 lg:grid-cols-[1fr_300px]">
<main>{/* Content */}</main>
<aside>{/* Sidebar */}</aside>
</div>
// Two column split
<div className="grid gap-6 md:grid-cols-2">
Navigation
<header className="border-b border-border">
<div className="container mx-auto flex h-16 items-center justify-between px-4">
<div className="flex items-center gap-6">
<Logo />
<nav className="hidden md:flex gap-6">
<a href="#" className="text-sm font-medium transition-colors hover:text-primary">
Dashboard
</a>
<a href="#" className="text-sm font-medium text-muted-foreground transition-colors hover:text-foreground">
Projects
</a>
</nav>
</div>
<div className="flex items-center gap-4">
<Button variant="ghost" size="sm">
<Bell className="h-4 w-4" />
</Button>
<Avatar>
<AvatarImage src={user.avatar} />
<AvatarFallback>{user.initials}</AvatarFallback>
</Avatar>
</div>
</div>
</header>
Best Practices
Component Organization
// ✅ Good: Small, focused components
export function UserCard({ user }) {
return (
<Card>
<CardHeader>
<UserAvatar user={user} />
<UserDetails user={user} />
</CardHeader>
</Card>
)
}
// ❌ Avoid: Large monolithic components
export function DashboardPage() {
// 500 lines of JSX...
}
Composability
// ✅ Compose shadcn components
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<MoreVertical className="h-4 w-4" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Share</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="text-destructive">
Delete
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
State Management
// Form state
const [formData, setFormData] = useState({ name: '', email: '' })
// Loading states
const [isLoading, setIsLoading] = useState(false)
// UI states
const [isOpen, setIsOpen] = useState(false)
Error Handling
<form onSubmit={handleSubmit} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input
id="email"
type="email"
className={errors.email ? "border-destructive" : ""}
/>
{errors.email && (
<p className="text-sm text-destructive">{errors.email}</p>
)}
</div>
</form>
Common Shadcn Components
Essential Components
- Layout: Card, Tabs, Sheet, Dialog, Popover, Separator
- Forms: Input, Textarea, Select, Checkbox, Radio, Switch, Label
- Buttons: Button, Toggle, ToggleGroup
- Display: Badge, Avatar, Skeleton, Table
- Feedback: Alert, Toast, Progress
- Navigation: NavigationMenu, DropdownMenu, Command
Button Variants
<Button>Primary</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="outline">Outline</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
<Button variant="destructive">Delete</Button>
Badge Variants
<Badge>Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="destructive">Error</Badge>
Workflow
- Understand requirements - What component/page is needed?
- Choose components - Which shadcn/ui components fit?
- Build structure - Layout and hierarchy first
- Apply styling - Typography, spacing, colors
- Add interactions - Hover states, transitions, focus
- Ensure accessibility - ARIA, keyboard, contrast
- Test responsive - Mobile, tablet, desktop
Quality Checklist
Before completing:
- Uses shadcn/ui components appropriately
- Follows 4px spacing scale (p-2, p-4, p-6, etc.)
- Uses semantic color tokens (bg-card, text-foreground, etc.)
- Limited shadow usage (shadow-sm/md/lg only)
- Smooth transitions (200-300ms duration)
- ARIA labels on interactive elements
- Keyboard focus visible (ring-2 ring-primary)
- WCAG AA contrast ratios
- Mobile-responsive layout
- Loading and error states handled
References
- Shadcn UI - Component library
- Tailwind CSS - Utility classes
- WCAG 2.1 - Accessibility standards
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
brainstorming
Use when creating or developing, before writing code or implementation plans - refines rough ideas into fully-formed designs through collaborative questioning, alternative exploration, and incremental validation. Don't use during clear 'mechanical' processes
frontend-design
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
expo-ios-designing
Designs modern, clean iOS screens and components for Expo React Native apps following Apple HIG with safe areas, Dynamic Type, dark mode, accessibility, Liquid Glass materials, and App Store readiness.
article-extractor
Extract clean article content from URLs (blog posts, articles, tutorials) and save as readable text. Use when user wants to download, extract, or save an article/blog post from a URL without ads, navigation, or clutter.
edit-article
Edit and improve articles by restructuring sections, improving clarity, and tightening prose. Use when user wants to edit, revise, or improve an article draft.
handoff
Compact the current conversation into a handoff document for another agent to pick up.
Didn't find tool you were looking for?