---
name: shadcn-ui
description: Guide for implementing shadcn/ui - a collection of beautifully-designed, accessible UI components built with Radix UI and Tailwind CSS. Use when building user interfaces, adding UI components, or implementing design systems in React-based applications.
license: MIT
version: 1.0.0
---
# shadcn/ui Skill
shadcn/ui is a collection of beautifully-designed, accessible components and a code distribution platform built with TypeScript, Tailwind CSS, and Radix UI primitives. It's not a traditional component library but a collection of reusable components you can copy and paste into your apps.
## Reference
https://ui.shadcn.com/llms.txt
## When to Use This Skill
Use this skill when:
- Building user interfaces with React-based frameworks (Next.js, Vite, Remix, Astro, etc.)
- Adding pre-built, accessible UI components to applications
- Implementing design systems with Tailwind CSS
- Setting up forms with validation (React Hook Form + Zod)
- Adding data tables, charts, or complex UI patterns
- Implementing dark mode with consistent theming
- Customizing component appearance and behavior
## Core Concepts
### Key Principles
- **Open Code**: Copy components into your project, modify freely
- **Composition**: Built with composable primitives from Radix UI
- **Distribution**: Components distributed via CLI, not npm packages
- **Beautiful Defaults**: Thoughtfully designed with excellent aesthetics
- **AI-Ready**: Structured for easy integration with AI tools
### Architecture
shadcn/ui follows a unique distribution model:
1. **CLI Tool**: Installs and manages components via `npx shadcn@latest`
2. **Component Registry**: Central repository of components
3. **Local Components**: Components live in your `components/ui/` directory
4. **Full Ownership**: You own the code, modify as needed
### Technology Stack
- **TypeScript**: Full type safety
- **Tailwind CSS**: Utility-first styling (v3 and v4 support)
- **Radix UI**: Accessible, unstyled primitives
- **Class Variance Authority**: Component variants
- **React 19**: Compatible with latest React
## Installation & Setup
### Initial Setup
**Using the CLI (Recommended):**
```bash
npx shadcn@latest init
```
The CLI will prompt for:
- Framework preference (Next.js, Vite, etc.)
- TypeScript or JavaScript
- Component installation location
- CSS variables or Tailwind configuration
- Color theme preferences
- Global CSS file location
**Manual Setup:**
1. Install dependencies:
```bash
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react
```
2. Create `components.json`:
```json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "app/globals.css",
"baseColor": "zinc",
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils"
}
}
```
3. Configure Tailwind:
```ts
// tailwind.config.ts
import type { Config } from "tailwindcss"
const config: Config = {
darkMode: ["class"],
content: [
'./pages/**/*.{ts,tsx}',
'./components/**/*.{ts,tsx}',
'./app/**/*.{ts,tsx}',
],
theme: {
extend: {},
},
plugins: [require("tailwindcss-animate")],
}
export default config
```
4. Create utility file:
```ts
// lib/utils.ts
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
```
### Adding Components
**Via CLI:**
```bash
# Add single component
npx shadcn@latest add button
# Add multiple components
npx shadcn@latest add button card dialog
# Add all components
npx shadcn@latest add --all
```
**What happens when you add a component:**
1. Component files are copied to `components/ui/`
2. Dependencies are automatically installed
3. Component is ready to import and use
## Component Categories
### Form & Input Components
**Button:**
```tsx
import { Button } from "@/components/ui/button"
```
**Input:**
```tsx
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
```
**Form (with validation):**
```tsx
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Button } from "@/components/ui/button"
const formSchema = z.object({
username: z.string().min(2).max(50),
email: z.string().email(),
})
function ProfileForm() {
const form = useForm>({
resolver: zodResolver(formSchema),
defaultValues: {
username: "",
email: "",
},
})
function onSubmit(values: z.infer) {
console.log(values)
}
return (
)
}
```
**Select:**
```tsx
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
```
**Checkbox:**
```tsx
import { Checkbox } from "@/components/ui/checkbox"
import { Label } from "@/components/ui/label"
```
**Date Picker:**
```tsx
import { Calendar } from "@/components/ui/calendar"
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
import { Button } from "@/components/ui/button"
import { CalendarIcon } from "lucide-react"
import { format } from "date-fns"
const [date, setDate] = useState()
```
### Layout & Navigation
**Card:**
```tsx
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
Card TitleCard Description
Card Content
Card Footer
```
**Tabs:**
```tsx
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
AccountPasswordAccount settingsPassword settings
```
**Accordion:**
```tsx
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
Is it accessible?
Yes. It adheres to the WAI-ARIA design pattern.
```
**Navigation Menu:**
```tsx
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
Item OneLink
```
### Overlays & Dialogs
**Dialog:**
```tsx
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
```
**Drawer:**
```tsx
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from "@/components/ui/drawer"
OpenAre you sure?This action cannot be undone.Cancel
```
**Popover:**
```tsx
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
OpenPlace content here.
```
**Toast:**
```tsx
import { useToast } from "@/hooks/use-toast"
import { Button } from "@/components/ui/button"
const { toast } = useToast()
```
**Command:**
```tsx
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from "@/components/ui/command"
No results found.CalendarSearch EmojiCalculator
```
### Feedback & Status
**Alert:**
```tsx
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
Heads up!
You can add components to your app using the CLI.
Error
Your session has expired. Please log in again.
```
**Progress:**
```tsx
import { Progress } from "@/components/ui/progress"
```
**Skeleton:**
```tsx
import { Skeleton } from "@/components/ui/skeleton"