Install any skill in seconds. Free to start, no credit card required.
Get Started Free →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.
.claude/skills/giuseppe-trisciuoglio-shadcn-ui/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 86% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 0% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 103% | 0% |
| case-21 | ✓→✓ | = Same ✓ | 179% | 0% |
| case-03 | ✓→✓ | = Same ✓ | 103% | 0% |
Build accessible, customizable UI components with shadcn/ui, Radix UI, and Tailwind CSS.
npx shadcn@latest add <component>Activate when user requests involve:
| Component | Install Command | Description | |-----------|----------------|-------------| | button | npx shadcn@latest add button | Variants: default, destructive, outline, secondary, ghost, link | | input | npx shadcn@latest add input | Text input field | | form | npx shadcn@latest add form | React Hook Form integration with validation | | card | npx shadcn@latest add card | Container with header, content, footer | | dialog | npx shadcn@latest add dialog | Modal overlay | | sheet | npx shadcn@latest add sheet | Slide-over panel (top/right/bottom/left) | | select | npx shadcn@latest add select | Dropdown select | | toast | npx shadcn@latest add toast | Notification toasts | | table | npx shadcn@latest add table | Data table | | menubar | npx shadcn@latest add menubar | Desktop-style menubar | | chart | npx shadcn@latest add chart | Recharts wrapper with theming | | textarea | npx shadcn@latest add textarea | Multi-line text input | | checkbox | npx shadcn@latest add checkbox | Checkbox input | | label | npx shadcn@latest add label | Accessible form label |
bash# New Next.js project npx create-next-app@latest my-app --typescript --tailwind --eslint --app cd my-app npx shadcn@latest init # Existing project npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react npx shadcn@latest init # Install components npx shadcn@latest add button input form card dialog select toast
tsx// Button with variants and sizes import { Button } from "@/components/ui/button" <Button variant="default">Default</Button> <Button variant="destructive" size="sm">Delete</Button> <Button variant="outline" disabled>Loading...</Button>
tsx"use client" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form" import { Input } from "@/components/ui/input" const formSchema = z.object({ email: z.string().email("Invalid email"), password: z.string().min(8, "Password must be at least 8 characters"), }) export function LoginForm() { const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { email: "", password: "" }, }) return ( <Form {...form}> <form onSubmit={form.handleSubmit(console.log)} className="space-y-4"> <FormField name="email" control={form.control} render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl><Input type="email" {...field} /></FormControl> <FormMessage /> </FormItem> )} /> <FormField name="password" control={form.control} render={({ field }) => ( <FormItem> <FormLabel>Password</FormLabel> <FormControl><Input type="password" {...field} /></FormControl> <FormMessage /> </FormItem> )} /> <Button type="submit">Login</Button> </form> </Form> ) }
See references/forms-and-validation.md for advanced multi-field forms, contact forms with API submission, and login card patterns.
tsximport { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" <Dialog> <DialogTrigger asChild> <Button variant="outline">Open</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Edit Profile</DialogTitle> </DialogHeader> {/* content */} </DialogContent> </Dialog>
tsx// 1. Add <Toaster /> to app/layout.tsx import { Toaster } from "@/components/ui/toaster" // 2. Use in components import { useToast } from "@/components/ui/use-toast" const { toast } = useToast() toast({ title: "Success", description: "Changes saved." }) toast({ variant: "destructive", title: "Error", description: "Something went wrong." })
tsximport { Bar, BarChart, CartesianGrid, XAxis } from "recharts" import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart" const chartConfig = { desktop: { label: "Desktop", color: "var(--chart-1)" }, } satisfies import("@/components/ui/chart").ChartConfig <ChartContainer config={chartConfig} className="min-h-[200px] w-full"> <BarChart data={data}> <CartesianGrid vertical={false} /> <XAxis dataKey="month" /> <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} /> <ChartTooltip content={<ChartTooltipContent />} /> </BarChart> </ChartContainer>
See references/charts-components.md for Line, Area, and Pie chart examples.
tsx"use client" import { zodResolver } from "@hookform/resolvers/zod" import { useForm } from "react-hook-form" import { z } from "zod" import { Button } from "@/components/ui/button" import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form" import { Input } from "@/components/ui/input" const formSchema = z.object({ email: z.string().email("Invalid email"), password: z.string().min(8, "Min 8 characters"), }) export function LoginForm() { const form = useForm<z.infer<typeof formSchema>>({ resolver: zodResolver(formSchema), defaultValues: { email: "", password: "" }, }) return ( <Form {...form}> <form onSubmit={form.handleSubmit(console.log)} className="space-y-4"> <FormField name="email" control={form.control} render={({ field }) => ( <FormItem> <FormLabel>Email</FormLabel> <FormControl><Input type="email" {...field} /></FormControl> <FormMessage /> </FormItem> )} /> <FormField name="password" control={form.control} render={({ field }) => ( <FormItem> <FormLabel>Password</FormLabel> <FormControl><Input type="password" {...field} /></FormControl> <FormMessage /> </FormItem> )} /> <Button type="submit">Login</Button> </form> </Form> ) }
tsximport { ColumnDef } from "@tanstack/react-table" import { Button } from "@/components/ui/button" import { Checkbox } from "@/components/ui/checkbox" import { DataTable } from "@/components/ui/data-table" const columns: ColumnDef<User>[] = [ { id: "select", header: ({ table }) => ( <Checkbox checked={table.getIsAllPageRowsSelected()} /> ), cell: ({ row }) => ( <Checkbox checked={row.getIsSelected()} /> )}, { accessorKey: "name", header: "Name" }, { accessorKey: "email", header: "Email" }, { id: "actions", cell: ({ row }) => ( <Button variant="ghost" size="sm">Edit</Button> )}, ]
tsximport { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog" <Dialog> <DialogTrigger asChild> <Button variant="outline">Add User</Button> </DialogTrigger> <DialogContent> <DialogHeader> <DialogTitle>Add New User</DialogTitle> </DialogHeader> {/* <LoginForm /> */} </DialogContent> </Dialog>
tsximport { useToast } from "@/components/ui/use-toast" import { Button } from "@/components/ui/button" const { toast } = useToast() toast({ title: "Saved", description: "Changes saved successfully." }) toast({ variant: "destructive", title: "Error", description: "Failed to save." })
"use client" for interactive components (hooks, events)globals.css for consistent design@ alias is configured in tsconfig.jsonnext-themesForm, FormField, FormItem, FormLabel, FormMessage together<Toaster /> once to root layoutnpx shadcn@latest add are fetched remotely; always verify the registry source is trusted before installation"use client" directive@radix-ui packages are installed@ alias in tsconfig.json for importsConsult these files for detailed patterns and code examples:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 14,048 | 12,322 | -12% | 1 | 1 | 0% | 3,054 | 5,684 | +86% | 0 | 0 | — |
case-02 | fail→pass | 36,396 | 10,544 | -71% | 1 | 1 | 0% | 5,278 | 5,285 | +0% | 0 | 0 | — |
case-21 | pass→pass | 9,786 | 11,637 | +19% | 1 | 1 | 0% | 1,937 | 5,400 | +179% | 0 | 0 | — |
case-03 | pass→pass | 11,285 | 7,574 | -33% | 1 | 1 | 0% | 2,121 | 4,314 | +103% | 0 | 0 | — |
case-04 | pass→pass | 3,746 | 3,393 | -9% | 1 | 1 | 0% | 650 | 3,550 | +446% | 0 | 0 | — |
case-05 | pass→pass | 11,302 | 5,058 | -55% | 1 | 1 | 0% | 2,072 | 3,930 | +90% | 0 | 0 | — |
case-06 | pass→pass | 10,419 | 5,682 | -45% | 1 | 1 | 0% | 1,972 | 4,088 | +107% | 0 | 0 | — |
case-07 | pass→pass | 6,502 | 3,886 | -40% | 1 | 1 | 0% | 1,184 | 3,668 | +210% | 0 | 0 | — |
case-08 | pass→pass | 13,565 | 12,464 | -8% | 1 | 1 | 0% | 2,429 | 5,440 | +124% | 0 | 0 | — |
case-09 | pass→pass | 7,131 | 4,040 | -43% | 1 | 1 | 0% | 1,339 | 3,727 | +178% | 0 | 0 | — |
case-10 | pass→pass | 3,624 | 3,527 | -3% | 1 | 1 | 0% | 623 | 3,548 | +470% | 0 | 0 | — |
case-22 | pass→pass | 20,572 | 15,171 | -26% | 1 | 1 | 0% | 4,425 | 6,269 | +42% | 0 | 0 | — |
case-11 | pass→pass | 4,505 | 2,451 | -46% | 1 | 1 | 0% | 739 | 3,414 | +362% | 0 | 0 | — |
case-12 | pass→pass | 5,873 | 2,740 | -53% | 1 | 1 | 0% | 976 | 3,419 | +250% | 0 | 0 | — |
case-13 | pass→pass | 5,933 | 1,764 | -70% | 1 | 1 | 0% | 865 | 3,137 | +263% | 0 | 0 | — |
case-14 | fail→fail | 30,818 | 29,902 | -3% | 1 | 1 | 0% | 1,297 | 3,911 | +202% | 0 | 0 | — |
case-15 | pass→pass | 12,463 | 6,887 | -45% | 1 | 1 | 0% | 1,998 | 4,132 | +107% | 0 | 0 | — |
case-16 | pass→pass | 4,671 | 4,907 | +5% | 1 | 1 | 0% | 803 | 3,861 | +381% | 0 | 0 | — |
case-17 | fail→pass | 10,613 | 2,661 | -75% | 1 | 1 | 0% | 1,678 | 3,414 | +103% | 0 | 0 | — |
case-18 | pass→pass | 6,317 | 2,813 | -55% | 1 | 1 | 0% | 1,237 | 3,374 | +173% | 0 | 0 | — |
case-19 | pass→pass | 5,391 | 4,029 | -25% | 1 | 1 | 0% | 916 | 3,648 | +298% | 0 | 0 | — |
case-20 | pass→pass | 14,190 | 12,382 | -13% | 1 | 1 | 0% | 2,603 | 5,543 | +113% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 21 counted toward the lift figure. The other 1 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +14 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.