8.6 KiB
8.6 KiB
shadcn/ui Component Reference
Overview
shadcn/ui provides a collection of re-usable components built with Radix UI and Tailwind CSS. Components are NOT installed as dependencies but copied into your project, giving you full control.
Installation Command
npx shadcn-ui@latest add [component-name]
Baseline Components for This Skill
The following components are installed by default:
Core UI Elements
- button: Primary interactive element with variants
- card: Container for grouped content
- input: Text input field
- label: Form label with accessibility support
- dialog: Modal dialog/overlay
- separator: Visual or semantic separator
Layout & Navigation
- sheet: Slide-over panel (mobile sidebar)
- dropdown-menu: Contextual menu with submenus
- navigation-menu: Main navigation component
Feedback & Notifications
- toast: Temporary notifications (via Sonner)
- alert: Static notification messages
- badge: Status or category indicator
Available Components by Category
Form Components
checkbox- Checkbox input with labelinput- Text input fieldlabel- Form labeltextarea- Multi-line text inputselect- Dropdown selectradio-group- Radio button groupswitch- Toggle switchslider- Range sliderform- Form wrapper with React Hook Form integrationcombobox- Searchable select (autocomplete)date-picker- Date selection with calendarcalendar- Calendar component
Layout Components
card- Content card with header/footersheet- Slide-over paneldialog- Modal dialogpopover- Floating popoverdrawer- Bottom drawer (mobile)separator- Divider linescroll-area- Custom scrollable areaaspect-ratio- Maintain aspect ratioresizable- Resizable panels
Navigation Components
navigation-menu- Main navigationmenubar- Desktop menu bardropdown-menu- Context/dropdown menucontext-menu- Right-click context menutabs- Tab navigationbreadcrumb- Breadcrumb navigationpagination- Page navigationcommand- Command palette (⌘K)
Feedback Components
toast- Toast notificationsalert- Alert messagesalert-dialog- Confirmation dialogbadge- Status badgeprogress- Progress indicatorskeleton- Loading skeletonspinner- Loading spinner
Data Display
table- Data tableavatar- User avatartooltip- Hover tooltipaccordion- Collapsible sectionscollapsible- Simple collapsiblehover-card- Rich hover carddata-table- Advanced data table with sorting/filtering
Utility Components
toggle- Toggle buttontoggle-group- Toggle button groupsonner- Toast notification library integrationcarousel- Image/content carousel
Usage Patterns
Adding a Single Component
npx shadcn-ui add button
This creates:
components/ui/button.tsx- Updates
components.jsonif needed
Adding Multiple Components
npx shadcn-ui add button card input label
Using a Component
import { Button } from "@/components/ui/button"
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card"
export default function Example() {
return (
<Card>
<CardHeader>
<CardTitle>Example Card</CardTitle>
</CardHeader>
<CardContent>
<Button>Click me</Button>
</CardContent>
</Card>
)
}
Component Composition Patterns
Form with Validation
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { toast } from "sonner"
const schema = z.object({
email: z.string().email(),
password: z.string().min(8)
})
export function LoginForm() {
const form = useForm({
resolver: zodResolver(schema)
})
const onSubmit = (data) => {
toast.success("Login successful!")
}
return (
<form onSubmit={form.handleSubmit(onSubmit)}>
<div>
<Label htmlFor="email">Email</Label>
<Input id="email" {...form.register("email")} />
</div>
<Button type="submit">Login</Button>
</form>
)
}
Dialog with Form
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
export function CreateDialog() {
return (
<Dialog>
<DialogTrigger asChild>
<Button>Create New</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Create Item</DialogTitle>
</DialogHeader>
<form>
<Input placeholder="Item name" />
<Button type="submit">Create</Button>
</form>
</DialogContent>
</Dialog>
)
}
Navigation with Dropdown
import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuLink } from "@/components/ui/navigation-menu"
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem } from "@/components/ui/dropdown-menu"
import { Button } from "@/components/ui/button"
export function AppNav() {
return (
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuLink href="/">Home</NavigationMenuLink>
</NavigationMenuItem>
<NavigationMenuItem>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost">Products</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Product A</DropdownMenuItem>
<DropdownMenuItem>Product B</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
)
}
Customization
Modifying Component Styles
Components use Tailwind classes and can be customized:
// Customize colors via CSS variables in globals.css
:root {
--primary: 200 100% 50%; /* Change primary color */
}
// Or override with props
<Button className="bg-purple-600 hover:bg-purple-700">
Custom Color
</Button>
Creating Variants
Use class-variance-authority (CVA) for variants:
import { cva } from "class-variance-authority"
const alertVariants = cva(
"rounded-lg border p-4",
{
variants: {
variant: {
default: "bg-background text-foreground",
destructive: "bg-destructive text-destructive-foreground",
success: "bg-green-50 text-green-900"
}
},
defaultVariants: {
variant: "default"
}
}
)
Accessibility Features
All shadcn/ui components include:
- [OK] Proper ARIA attributes
- [OK] Keyboard navigation
- [OK] Focus management
- [OK] Screen reader support
- [OK] Reduced motion support
Example: Dialog Accessibility
<Dialog>
{/* Auto-handled: */}
{/* - Focus trap */}
{/* - ESC to close */}
{/* - aria-labelledby */}
{/* - Backdrop click to close */}
<DialogContent>
<DialogHeader>
<DialogTitle>Title (used for aria-labelledby)</DialogTitle>
</DialogHeader>
</DialogContent>
</Dialog>
Best Practices
1. Always Use Labels with Inputs
[OK] Good
<div>
<Label htmlFor="username">Username</Label>
<Input id="username" />
</div>
[ERROR] Bad
<Input placeholder="Username" /> {/* Placeholder is not a label */}
2. Provide Accessible Names
[OK] Good
<Button aria-label="Close menu">
<X className="h-4 w-4" />
</Button>
[ERROR] Bad
<Button>
<X className="h-4 w-4" /> {/* No text or aria-label */}
</Button>
3. Handle Loading States
<Button disabled={isLoading}>
{isLoading ? "Loading..." : "Submit"}
</Button>
4. Use Semantic HTML
[OK] Good
<form onSubmit={handleSubmit}>
<Button type="submit">Submit</Button>
</form>
[ERROR] Bad
<div onClick={handleSubmit}>
<Button type="button">Submit</Button>
</div>
Resources
- Official Docs: https://ui.shadcn.com
- Component Examples: https://ui.shadcn.com/examples
- Radix UI Docs: https://radix-ui.com
- GitHub: https://github.com/shadcn-ui/ui
Integration with This Skill
The skill installs these baseline components automatically:
button- Primary actionscard- Content containersinput- Form inputslabel- Form labelsdialog- Modalsseparator- Visual dividers
Additional components can be added as needed:
npx shadcn-ui add [component-name]