Build accessible, customizable UIs with shadcn/ui, Radix UI, and Tailwind CSS. Use when setting up shadcn/ui, installing components, building forms with React Hook Form + Zod, customizing themes, or implementing component patterns.
数据来源:ClawHub。 在 ClawSkills 查看
选择你使用的 Agent
方法一:命令行安装(推荐)
推荐(无需提前安装 clawhub)
npx clawhub@latest --dir ~/.claude/skills install shadcn或使用 clawhub CLI(需提前安装)
clawhub --dir ~/.claude/skills install shadcn⚠️ 需要 Node.js 18+,没有 Node?请使用下方方法二直接下载 ZIP。 安装 Node.js →
方法二:手动下载安装(无需 Node)
下载 ZIP,解压后将文件夹放到以下路径,重启 Agent 即可:
安装路径
~/.claude/skills/shadcn/💡解压后将文件夹放到上方路径,重启 Agent 即可生效
--- name: shadcn-ui model: fast description: Build accessible, customizable UIs with shadcn/ui, Radix UI, and Tailwind CSS. Use when setting up shadcn/ui, installing components, building forms with React Hook Form + Zod, customizing themes, or implementing component patterns. keywords: [shadcn, shadcn/ui, radix ui, tailwind, react components, forms, react hook form, zod, dialog, sheet, button, card, toast, select, dropdown, table, accessible components] ---
Expert guide for building accessible, customizable UI components with shadcn/ui.
npx clawhub@latest install shadcn-ui
A collection of reusable components you copy into your project — not an npm package. You own the code. Built on Radix UI (accessibility) and Tailwind CSS (styling).
# New Next.js project
npx create-next-app@latest my-app --typescript --tailwind --eslint --app
cd my-app
npx shadcn@latest init
# Install components
npx shadcn@latest add button input form card dialog select toast
npx shadcn@latest add --all # or install everything
cn UtilityMerges Tailwind classes with conflict resolution — used in every component:
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Manages component variants — the pattern behind every shadcn/ui component:
import { cva, type VariantProps } 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 hover:bg-destructive/90",
outline: "border border-input bg-background hover:bg-accent",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/90",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
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",
},
},
defaultVariants: { variant: "default", size: "default" },
}
)
import { Button } from "@/components/ui/button"
import { Loader2 } from "lucide-react"
// Variants: default | destructive | outline | secondary | ghost | link
// Sizes: default | sm | lg | icon
<Button variant="outline" size="sm">Click me</Button>
// Loading state
<Button disabled>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
Please wait
</Button>
// As link (uses Radix Slot)
<Button asChild>
<a href="/dashboard">Go to Dashboard</a>
</Button>
The standard pattern: Zod schema + React Hook Form + shadcn Form components.
npx shadcn@latest add form input select checkbox textarea
"use client"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import {
Form, FormControl, FormDescription,
FormField, FormItem, FormLabel, FormMessage,
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
const formSchema = z.object({
username: z.string().min(2, "Username must be at least 2 characters."),
email: z.string().email("Please enter a valid email."),
role: z.enum(["admin", "user", "guest"]),
})
export function ProfileForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: { username: "", email: "", role: "user" },
})
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<FormField control={form.control} name="username" render={({ field }) => (
<FormItem>
<FormLabel>Username</FormLabel>
<FormControl><Input placeholder="shadcn" {...field} /></FormControl>
<FormDescription>Your public display name.</FormDescription>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="email" render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl><Input type="email" {...field} /></FormControl>
<FormMessage />
</FormItem>
)} />
<FormField control={form.control} name="role" render={({ field }) => (
<FormItem>
<FormLabel>Role</FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger><SelectValue placeholder="Select a role" /></SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value="admin">Admin</SelectItem>
<SelectItem value="user">User</SelectItem>
<SelectItem value="guest">Guest</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)} />
<Button type="submit">Submit</Button>
</form>
</Form>
)
}
import {
Dialog, DialogContent, DialogDescription,
DialogFooter, DialogHeader, DialogTitle, DialogTrigger,
} from "@/components/ui/dialog"
import {
Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger,
} from "@/components/ui/sheet"
// Modal dialog
<Dialog>
<DialogTrigger asChild><Button variant="outline">Edit profile</Button></DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>Make changes here. Click save when done.</DialogDescription>
</DialogHeader>
<div className="grid gap-4 py-4">{/* form fields */}</div>
<DialogFooter><Button type="submit">Save changes</Button></DialogFooter>
</DialogContent>
</Dialog>
// Slide-over panel (side: "left" | "right" | "top" | "bottom")
<Sheet>
<SheetTrigger asChild><Button variant="outline">Open</Button></SheetTrigger>
<SheetContent side="right">
<SheetHeader><SheetTitle>Settings</SheetTitle></SheetHeader>
{/* content */}
</SheetContent>
</Sheet>
import {
Card, CardContent, CardDescription,
CardFooter, CardHeader, CardTitle,
} from "@/components/ui/card"
<Card className="w-[350px]">
<CardHeader>
<CardTitle>Create project</CardTitle>
<CardDescription>Deploy your new project in one-click.</CardDescription>
</CardHeader>
<CardContent>
<div className="grid w-full items-center gap-4">
<div className="flex flex-col space-y-1.5">
<Label htmlFor="name">Name</Label>
<Input id="name" placeholder="Project name" />
</div>
</div>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="outline">Cancel</Button>
<Button>Deploy</Button>
</CardFooter>
</Card>
// 1. Add Toaster to root layout
import { Toaster } from "@/components/ui/toaster"
...安装 Shadcn UI 后,可以对 AI 说这些话来触发它
Help me get started with Shadcn UI
Explains what Shadcn UI does, walks through the setup, and runs a quick demo based on your current project
Use Shadcn UI to build accessible, customizable UIs with shadcn/ui, Radix UI, and Ta...
Invokes Shadcn UI with the right parameters and returns the result directly in the conversation
What can I do with Shadcn UI in my developer & devops workflow?
Lists the top use cases for Shadcn UI, with example commands for each scenario
将技能文件夹放到 ~/.claude/skills/shadcn/ 目录(个人级,所有项目可用),或 .claude/skills/shadcn/(项目级)。重启 AI 客户端后,用 /shadcn 主动调用,或让 AI 根据上下文自动发现并使用。
Shadcn UI 支持 Claude、Cursor、OpenClaw,可与这些 AI 平台无缝集成,扩展其能力。
Shadcn UI 可免费安装使用。请查阅仓库了解许可证信息。
Build accessible, customizable UIs with shadcn/ui, Radix UI, and Tailwind CSS. Use when setting up shadcn/ui, installing components, building forms with React Hook Form + Zod, customizing themes, or implementing component patterns.
Shadcn UI 属于「Developer & DevOps」分类,该分类的技能帮助 AI 智能体在此领域执行专业任务。
Automate my developer & devops tasks using Shadcn UI
Identifies repetitive steps in your workflow and sets up Shadcn UI to handle them automatically