Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build React UIs using shadcn/ui components with Tailwind CSS, Radix primitives, and proper accessibility patterns.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
SKILL.md
1---2name: shadcn-ui3description: Provides complete shadcn/ui component library patterns including installation, configuration, and implementation of accessible React components. Use when setting up shadcn/ui, installing components, building forms with React Hook Form and Zod, customizing themes with Tailwind CSS, or implementing UI patterns like buttons, dialogs, dropdowns, tables, and complex form layouts.4allowed-tools: Read, Write, Bash, Edit, Glob5---67# shadcn/ui Component Patterns89Build accessible, customizable UI components with shadcn/ui, Radix UI, and Tailwind CSS.1011## Overview1213- Components are **copied into your project** — you own and customize the code14- Built on **Radix UI** primitives for full accessibility15- Styled with **Tailwind CSS** and CSS variables for theming16- CLI-based installation: `npx shadcn@latest add <component>`1718## When to Use1920Activate when user requests involve:21- "Set up shadcn/ui", "initialize shadcn", "add shadcn components"22- "Install button/input/form/dialog/card/select/toast/table/chart"23- "React Hook Form", "Zod validation", "form with validation"24- "accessible components", "Radix UI", "Tailwind theme"25- "shadcn button", "shadcn dialog", "shadcn sheet", "shadcn table"26- "dark mode", "CSS variables", "custom theme"27- "charts with Recharts", "bar chart", "line chart", "pie chart"2829## Quick Reference3031### Available Components3233| Component | Install Command | Description |34|-----------|----------------|-------------|35| `button` | `npx shadcn@latest add button` | Variants: default, destructive, outline, secondary, ghost, link |36| `input` | `npx shadcn@latest add input` | Text input field |37| `form` | `npx shadcn@latest add form` | React Hook Form integration with validation |38| `card` | `npx shadcn@latest add card` | Container with header, content, footer |39| `dialog` | `npx shadcn@latest add dialog` | Modal overlay |40| `sheet` | `npx shadcn@latest add sheet` | Slide-over panel (top/right/bottom/left) |41| `select` | `npx shadcn@latest add select` | Dropdown select |42| `toast` | `npx shadcn@latest add toast` | Notification toasts |43| `table` | `npx shadcn@latest add table` | Data table |44| `menubar` | `npx shadcn@latest add menubar` | Desktop-style menubar |45| `chart` | `npx shadcn@latest add chart` | Recharts wrapper with theming |46| `textarea` | `npx shadcn@latest add textarea` | Multi-line text input |47| `checkbox` | `npx shadcn@latest add checkbox` | Checkbox input |48| `label` | `npx shadcn@latest add label` | Accessible form label |4950## Instructions5152### Initialize Project5354```bash55# New Next.js project56npx create-next-app@latest my-app --typescript --tailwind --eslint --app57cd my-app58npx shadcn@latest init5960# Existing project61npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react62npx shadcn@latest init6364# Install components65npx shadcn@latest add button input form card dialog select toast66```6768### Basic Component Usage6970```tsx71// Button with variants and sizes72import { Button } from "@/components/ui/button"7374<Button variant="default">Default</Button>75<Button variant="destructive" size="sm">Delete</Button>76<Button variant="outline" disabled>Loading...</Button>77```7879### Form with Zod Validation8081```tsx82"use client"8384import { zodResolver } from "@hookform/resolvers/zod"85import { useForm } from "react-hook-form"86import { z } from "zod"87import { Button } from "@/components/ui/button"88import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"89import { Input } from "@/components/ui/input"9091const formSchema = z.object({92email: z.string().email("Invalid email"),93password: z.string().min(8, "Password must be at least 8 characters"),94})9596export function LoginForm() {97const form = useForm<z.infer<typeof formSchema>>({98resolver: zodResolver(formSchema),99defaultValues: { email: "", password: "" },100})101102return (103<Form {...form}>104<form onSubmit={form.handleSubmit(console.log)} className="space-y-4">105<FormField name="email" control={form.control} render={({ field }) => (106<FormItem>107<FormLabel>Email</FormLabel>108<FormControl><Input type="email" {...field} /></FormControl>109<FormMessage />110</FormItem>111)} />112<FormField name="password" control={form.control} render={({ field }) => (113<FormItem>114<FormLabel>Password</FormLabel>115<FormControl><Input type="password" {...field} /></FormControl>116<FormMessage />117</FormItem>118)} />119<Button type="submit">Login</Button>120</form>121</Form>122)123}124```125126See [references/forms-and-validation.md](references/forms-and-validation.md) for advanced multi-field forms, contact forms with API submission, and login card patterns.127128### Dialog (Modal)129130```tsx131import { Button } from "@/components/ui/button"132import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"133134<Dialog>135<DialogTrigger asChild>136<Button variant="outline">Open</Button>137</DialogTrigger>138<DialogContent>139<DialogHeader>140<DialogTitle>Edit Profile</DialogTitle>141</DialogHeader>142{/* content */}143</DialogContent>144</Dialog>145```146147### Toast Notification148149```tsx150// 1. Add <Toaster /> to app/layout.tsx151import { Toaster } from "@/components/ui/toaster"152153// 2. Use in components154import { useToast } from "@/components/ui/use-toast"155156const { toast } = useToast()157toast({ title: "Success", description: "Changes saved." })158toast({ variant: "destructive", title: "Error", description: "Something went wrong." })159```160161### Bar Chart162163```tsx164import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"165import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"166167const chartConfig = {168desktop: { label: "Desktop", color: "var(--chart-1)" },169} satisfies import("@/components/ui/chart").ChartConfig170171<ChartContainer config={chartConfig} className="min-h-[200px] w-full">172<BarChart data={data}>173<CartesianGrid vertical={false} />174<XAxis dataKey="month" />175<Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />176<ChartTooltip content={<ChartTooltipContent />} />177</BarChart>178</ChartContainer>179```180181See [references/charts-components.md](references/charts-components.md) for Line, Area, and Pie chart examples.182183## Examples184185### Login Form with Validation186```tsx187"use client"188import { zodResolver } from "@hookform/resolvers/zod"189import { useForm } from "react-hook-form"190import { z } from "zod"191import { Button } from "@/components/ui/button"192import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"193import { Input } from "@/components/ui/input"194195const formSchema = z.object({196email: z.string().email("Invalid email"),197password: z.string().min(8, "Min 8 characters"),198})199200export function LoginForm() {201const form = useForm<z.infer<typeof formSchema>>({202resolver: zodResolver(formSchema),203defaultValues: { email: "", password: "" },204})205206return (207<Form {...form}>208<form onSubmit={form.handleSubmit(console.log)} className="space-y-4">209<FormField name="email" control={form.control} render={({ field }) => (210<FormItem>211<FormLabel>Email</FormLabel>212<FormControl><Input type="email" {...field} /></FormControl>213<FormMessage />214</FormItem>215)} />216<FormField name="password" control={form.control} render={({ field }) => (217<FormItem>218<FormLabel>Password</FormLabel>219<FormControl><Input type="password" {...field} /></FormControl>220<FormMessage />221</FormItem>222)} />223<Button type="submit">Login</Button>224</form>225</Form>226)227}228```229230### Data Table with Actions231```tsx232import { ColumnDef } from "@tanstack/react-table"233import { Button } from "@/components/ui/button"234import { Checkbox } from "@/components/ui/checkbox"235import { DataTable } from "@/components/ui/data-table"236237const columns: ColumnDef<User>[] = [238{ id: "select", header: ({ table }) => (239<Checkbox checked={table.getIsAllPageRowsSelected()} />240), cell: ({ row }) => (241<Checkbox checked={row.getIsSelected()} />242)},243{ accessorKey: "name", header: "Name" },244{ accessorKey: "email", header: "Email" },245{ id: "actions", cell: ({ row }) => (246<Button variant="ghost" size="sm">Edit</Button>247)},248]249```250251### Dialog with Form252```tsx253import { Button } from "@/components/ui/button"254import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"255256<Dialog>257<DialogTrigger asChild>258<Button variant="outline">Add User</Button>259</DialogTrigger>260<DialogContent>261<DialogHeader>262<DialogTitle>Add New User</DialogTitle>263</DialogHeader>264{/* <LoginForm /> */}265</DialogContent>266</Dialog>267```268269### Toast Notifications270```tsx271import { useToast } from "@/components/ui/use-toast"272import { Button } from "@/components/ui/button"273274const { toast } = useToast()275276toast({ title: "Saved", description: "Changes saved successfully." })277toast({ variant: "destructive", title: "Error", description: "Failed to save." })278```279280## Best Practices281282- **Accessibility**: Use Radix UI primitives — ARIA attributes are built in283- **Client Components**: Add `"use client"` for interactive components (hooks, events)284- **Type Safety**: Use TypeScript and Zod schemas for form validation285- **Theming**: Configure CSS variables in `globals.css` for consistent design286- **Customization**: Modify component files directly — you own the code287- **Path Aliases**: Ensure `@` alias is configured in `tsconfig.json`288- **Registry Security**: Only install components from trusted registries; review generated code before production use289- **Dark Mode**: Set up with CSS variables strategy and `next-themes`290- **Forms**: Always use `Form`, `FormField`, `FormItem`, `FormLabel`, `FormMessage` together291- **Toaster**: Add `<Toaster />` once to root layout292293## Constraints and Warnings294295- **Not an NPM Package**: Components are copied to your project; they are not a versioned dependency296- **Registry Security**: Components from `npx shadcn@latest add` are fetched remotely; always verify the registry source is trusted before installation297- **Client Components**: Most interactive components require `"use client"` directive298- **Radix Dependencies**: Ensure all `@radix-ui` packages are installed299- **Tailwind Required**: Components rely on Tailwind CSS utilities300- **Path Aliases**: Configure `@` alias in `tsconfig.json` for imports301302## References303304Consult these files for detailed patterns and code examples:305306- **[references/setup-and-configuration.md](references/setup-and-configuration.md)** — Full installation, tsconfig, tailwind config, CSS variables307- **[references/ui-components.md](references/ui-components.md)** — Button, Input, Card, Dialog, Sheet, Select, Toast, Table, Menubar308- **[references/forms-and-validation.md](references/forms-and-validation.md)** — React Hook Form + Zod, advanced forms, login card, contact form309- **[references/charts-components.md](references/charts-components.md)** — Bar, Line, Area, Pie charts with ChartContainer and theming310- **[references/nextjs-integration.md](references/nextjs-integration.md)** — App Router, Server/Client Components, dark mode, metadata311- **[references/customization.md](references/customization.md)** — Custom variants, CSS variables, cn() utility, extending components312