Component Catalogue
The ~15 most-used shadcn/ui components with install commands, key props, and gotchas. Not exhaustive — see shadcn/ui docs for the full list.
Button
pnpm dlx shadcn@latest add button
Variants: default, destructive, outline, secondary, ghost, link
Sizes: default, sm, lg, icon
<Button variant="outline" size="sm"
<Button variant="ghost" size="icon"><Trash className="h-4 w-4" /></Button>
<Button disabled={isPending}>{isPending ? 'Saving...' : 'Save'}</Button>
Input + Label
pnpm dlx shadcn@latest add input label
<div className="space-y-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" placeholder="you@example.com" />
</div>
Note: When using with react-hook-form, don't spread {...field} — pass props individually to avoid null value issues.
Card
pnpm dlx shadcn@latest add card
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
<CardDescription>Description</CardDescription>
</CardHeader>
<CardContent>Body</CardContent>
<CardFooter>Footer</CardFooter>
</Card>
Form
pnpm dlx shadcn@latest add form
pnpm add react-hook-form zod @hookform/resolvers
Wraps react-hook-form with shadcn styling. See recipes.md for complete form examples.
Key exports: Form, FormField, FormItem, FormLabel, FormControl, FormMessage
Dialog
pnpm dlx shadcn@latest add dialog
<Dialog open={open}
<DialogTrigger asChild><Button>Open</Button></DialogTrigger>
<DialogContent className="sm:max-w-md">
<DialogHeader>
<DialogTitle>Title</DialogTitle>
<DialogDescription>Description</DialogDescription>
</DialogHeader>
{/* content */}
<DialogFooter>
<Button => setOpen(false)}>Close</Button>
</DialogFooter>
</DialogContent>
</Dialog>
Gotcha: Override width with sm:max-w-* (must match breakpoint prefix).
Sheet
pnpm dlx shadcn@latest add sheet
Side panel — commonly used for mobile navigation.
<Sheet>
<SheetTrigger asChild><Button variant="ghost" size="icon"><Menu /></Button></SheetTrigger>
<SheetContent side="left">
<SheetHeader><SheetTitle>Navigation</SheetTitle></SheetHeader>
{/* nav links */}
</SheetContent>
</Sheet>
Sides: left, right, top, bottom
Table
pnpm dlx shadcn@latest add table
Static table. For sortable/filterable data tables, also install @tanstack/react-table. See recipes.md for the data table pattern.
<Table>
<TableHeader>
<TableRow><TableHead>Name</TableHead><TableHead>Email</TableHead></TableRow>
</TableHeader>
<TableBody>
{users.map(u => (
<TableRow key={u.id}>
<TableCell>{u.name}</TableCell>
<TableCell>{u.email}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
Select
pnpm dlx shadcn@latest add select
<Select value={value}
<SelectTrigger><SelectValue placeholder="Choose..." /></SelectTrigger>
<SelectContent>
<SelectItem value="option1">Option 1</SelectItem>
<SelectItem value="option2">Option 2</SelectItem>
</SelectContent>
</Select>
Gotcha: No empty string values. Use "__any__" sentinel for "All" options.
Toast (Sonner)
pnpm dlx shadcn@latest add toast
pnpm add sonner
Add <Toaster /> to your root layout, then:
import { toast } from 'sonner'
toast.success('Saved successfully')
toast.error('Something went wrong')
toast.promise(saveData(), {
loading: 'Saving...',
success: 'Saved!',
error: 'Failed to save',
})
Tabs
pnpm dlx shadcn@latest add tabs
<Tabs defaultValue="general">
<TabsList>
<TabsTrigger value="general">General</TabsTrigger>
<TabsTrigger value="security">Security</TabsTrigger>
</TabsList>
<TabsContent value="general">General settings...</TabsContent>
<TabsContent value="security">Security settings...</TabsContent>
</Tabs>
Dropdown Menu
pnpm dlx shadcn@latest add dropdown-menu
<DropdownMenu>
<DropdownMenuTrigger asChild><Button variant="ghost" size="icon"><MoreHorizontal /></Button></DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem
<DropdownMenuSeparator />
<DropdownMenuItem className="text-destructive"
</DropdownMenuContent>
</DropdownMenu>
Badge
pnpm dlx shadcn@latest add badge
Variants: default, secondary, outline, destructive
<Badge variant="secondary">Draft</Badge>
<Badge variant="destructive">Overdue</Badge>
Switch
pnpm dlx shadcn@latest add switch
<div className="flex items-center gap-2">
<Switch id="notifications" checked={enabled} />
<Label htmlFor="notifications">Enable notifications</Label>
</div>
Separator
pnpm dlx shadcn@latest add separator
<Separator /> {/* horizontal */}
<Separator orientation="vertical" className="h-6" /> {/* vertical */}
Avatar
pnpm dlx shadcn@latest add avatar
<Avatar>
<AvatarImage src={user.avatar} alt={user.name} />
<AvatarFallback>{user.name[0]}</AvatarFallback>
</Avatar>