---
name: frontend-shadcn
description: DEFAULT foundation component library for all React/Next.js UI needs. Use as the starting point for any project needing buttons, inputs, dialogs, forms, tables, navigation, modals, dropdowns, and other standard UI elements. Built on Radix UI + Tailwind CSS. Check shadcn FIRST before reaching for other libraries.
allowed-tools: Read, Edit, Write, Bash (*)
---
# shadcn/ui Component Library
## Overview
shadcn/ui is NOT a component library you install via npm. It's a collection of re-usable components that you copy and paste into your project. You OWN the code.
**Philosophy:** Copy-paste → Own the code → Customize freely
**Built on:** Radix UI (accessibility) + Tailwind CSS (styling) + CVA (variants)
## When to Use This Skill
- Starting ANY new React/Next.js project
- Need standard UI components (buttons, inputs, dialogs, etc.)
- Building forms, tables, navigation
- Need accessible, production-ready components
- User asks for "basic UI", "form", "modal", "dropdown", etc.
**This is your DEFAULT starting point. Always check shadcn/ui first.**
---
## Quick Start
### Project Setup
```bash
# Initialize shadcn/ui in your project
npx shadcn@latest init
# Answer prompts:
# - Style: Default or New York
# - Base color: Slate, Gray, Zinc, Neutral, Stone
# - CSS variables: Yes (recommended)
```
### Add Components
```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
```
---
## Complete Component Reference
### Forms & Inputs
| Component | Command | Use Case |
|-----------|---------|----------|
| **Button** | `add button` | Primary actions, CTAs |
| **Input** | `add input` | Text fields |
| **Textarea** | `add textarea` | Multi-line text |
| **Select** | `add select` | Dropdown selection |
| **Native Select** | `add native-select` | Native HTML select |
| **Checkbox** | `add checkbox` | Boolean options |
| **Radio Group** | `add radio-group` | Single choice from options |
| **Switch** | `add switch` | Toggle on/off |
| **Slider** | `add slider` | Range selection |
| **Input OTP** | `add input-otp` | One-time password input |
| **Form** | `add form` | Form with react-hook-form + zod |
| **Label** | `add label` | Form field labels |
| **Field** | `add field` | Form field wrapper |
```tsx
// Button variants
```
```tsx
// Form example with validation
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
export function LoginForm() {
const form = useForm({
resolver: zodResolver(schema),
})
return (
)
}
```
### Overlays & Modals
| Component | Command | Use Case |
|-----------|---------|----------|
| **Dialog** | `add dialog` | Modal windows, confirmations |
| **Alert Dialog** | `add alert-dialog` | Destructive action confirmations |
| **Sheet** | `add sheet` | Side panels (mobile nav, filters) |
| **Drawer** | `add drawer` | Bottom sheets (mobile) |
| **Popover** | `add popover` | Floating content, pickers |
| **Tooltip** | `add tooltip` | Hover hints |
| **Hover Card** | `add hover-card` | Rich hover previews |
| **Context Menu** | `add context-menu` | Right-click menus |
| **Dropdown Menu** | `add dropdown-menu` | Action menus |
```tsx
// Dialog example
```
```tsx
// Sheet (side panel)
{/* left | right | top | bottom */}
Menu
{/* navigation links */}
```
### Navigation
| Component | Command | Use Case |
|-----------|---------|----------|
| **Navigation Menu** | `add navigation-menu` | Main site navigation |
| **Menubar** | `add menubar` | App menubar (File, Edit, View) |
| **Breadcrumb** | `add breadcrumb` | Page hierarchy |
| **Pagination** | `add pagination` | Page navigation |
| **Tabs** | `add tabs` | Content sections |
| **Command** | `add command` | Command palette (⌘K) |
| **Sidebar** | `add sidebar` | App sidebar navigation |
```tsx
// Tabs example
Account
Password
Account settings...
Password settings...
```
```tsx
// Command palette (cmdk)
No results found.
Calendar
Search
Settings
```
### Layout & Structure
| Component | Command | Use Case |
|-----------|---------|----------|
| **Card** | `add card` | Content containers |
| **Accordion** | `add accordion` | Collapsible sections |
| **Collapsible** | `add collapsible` | Toggle content visibility |
| **Separator** | `add separator` | Visual dividers |
| **Aspect Ratio** | `add aspect-ratio` | Fixed aspect containers |
| **Scroll Area** | `add scroll-area` | Custom scrollbars |
| **Resizable** | `add resizable` | Resizable panels |
```tsx
// Card example
Card Title
Card description
Card content here
```
```tsx
// Accordion
Is it accessible?
Yes. It follows WAI-ARIA patterns.
```
### Data Display
| Component | Command | Use Case |
|-----------|---------|----------|
| **Table** | `add table` | Basic tables |
| **Data Table** | `add data-table` | Advanced tables (sorting, filtering) |
| **Avatar** | `add avatar` | User images |
| **Badge** | `add badge` | Status labels, tags |
| **Calendar** | `add calendar` | Date picker calendar |
| **Date Picker** | `add date-picker` | Date selection |
| **Carousel** | `add carousel` | Image/content sliders |
| **Chart** | `add chart` | Data visualization (Recharts) |
```tsx
// Table
Name
Email
Status
John Doe
john@example.com
Active
```
```tsx
// Badge variants
Default
Secondary
Error
Outline
```
### Feedback
| Component | Command | Use Case |
|-----------|---------|----------|
| **Alert** | `add alert` | Inline messages |
| **Toast** | `add toast` | Brief notifications |
| **Sonner** | `add sonner` | Better toast notifications |
| **Progress** | `add progress` | Loading progress |
| **Skeleton** | `add skeleton` | Loading placeholders |
| **Spinner** | `add spinner` | Loading indicator |
| **Empty** | `add empty` | Empty state placeholder |
```tsx
// Alert
Heads up!
You can add components to your app.
Error
Something went wrong.
```
```tsx
// Toast (using Sonner - recommended)
import { toast } from "sonner"
// Trigger toast
toast.success("Profile updated!")
toast.error("Something went wrong")
toast.loading("Saving...")
```
```tsx
// Skeleton loading
```
### Utility
| Component | Command | Use Case |
|-----------|---------|----------|
| **Toggle** | `add toggle` | On/off button |
| **Toggle Group** | `add toggle-group` | Multiple toggles |
| **Combobox** | `add combobox` | Searchable select |
| **Typography** | `add typography` | Text styles |
| **Kbd** | `add kbd` | Keyboard shortcut hints |
| **Button Group** | `add button-group` | Grouped buttons |
| **Input Group** | `add input-group` | Input with addons |
| **Item** | `add item` | List item component |
```tsx
// Combobox (searchable select)
No results.
{frameworks.map((framework) => (
setValue(framework.value)}
>
{framework.label}
))}
```
---
## Common Patterns
### Loading Button
```tsx
import { Loader2 } from "lucide-react"
```
### Confirmation Dialog
```tsx
Are you sure?
This action cannot be undone.
Cancel
Delete
```
### Search with Command
```tsx
```
### Responsive Mobile Menu
```tsx
// Desktop: Navigation Menu
// Mobile: Sheet with menu
{/* desktop nav */}
{/* mobile nav links */}
```
---
## Theming
### CSS Variables (globals.css)
```css
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 240 10% 3.9%;
--primary: 240 5.9% 10%;
--primary-foreground: 0 0% 98%;
--secondary: 240 4.8% 95.9%;
--secondary-foreground: 240 5.9% 10%;
--muted: 240 4.8% 95.9%;
--muted-foreground: 240 3.8% 46.1%;
--accent: 240 4.8% 95.9%;
--accent-foreground: 240 5.9% 10%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 0 0% 98%;
--border: 240 5.9% 90%;
--input: 240 5.9% 90%;
--ring: 240 5.9% 10%;
--radius: 0.5rem;
}
.dark {
--background: 240 10% 3.9%;
--foreground: 0 0% 98%;
/* ... dark mode values */
}
}
```
### Using Theme Colors
```tsx
// In Tailwind classes
```
---
## Component Customization
### Extending Variants (CVA)
```tsx
// components/ui/button.tsx
import { cva } from "class-variance-authority"
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground",
outline: "border border-input bg-background hover:bg-accent",
secondary: "bg-secondary text-secondary-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
// Add custom variants
success: "bg-green-600 text-white hover:bg-green-700",
warning: "bg-yellow-500 text-black hover:bg-yellow-600",
},
size: {
default: "h-10 px-4 py-2",
sm: "h-9 rounded-md px-3",
lg: "h-11 rounded-md px-8",
icon: "h-10 w-10",
// Add custom sizes
xl: "h-14 rounded-lg px-10 text-lg",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
```
---
## Decision Guide
```
Need a component?
│
▼
┌──────────────────────────┐
│ Is it a STANDARD UI │
│ element? (button, input, │
│ modal, table, form...) │
└──────────────────────────┘
│
YES ─┴─ NO
│ │
▼ ▼
shadcn Check Aceternity
/ui or Magic UI
```
---
## Troubleshooting
```yaml
"Component not found":
→ npx shadcn@latest add [component] --overwrite
→ Check components.json exists
"Styles not applying":
→ Check tailwind.config.ts content paths
→ Check globals.css has CSS variables
"Hydration mismatch (Dialog/Sheet)":
→ Add suppressHydrationWarning to
→ Use dynamic(() => import(...), { ssr: false })
"Dark mode not working":
→ npm install next-themes
→ Add darkMode: ['class'] to tailwind.config.ts
→ Wrap app with ThemeProvider
"Form errors not showing":
→ Include in FormField
→ Check zodResolver(schema) is set
```
---
## References
- **[patterns.md](references/patterns.md)** — Dark mode toggle, multi-step forms, data tables, file upload
## External Resources
- https://ui.shadcn.com/docs — Documentation
- https://ui.shadcn.com/docs/components — Components list
- https://ui.shadcn.com/themes — Theme generator
- https://ui.shadcn.com/blocks — Example blocks