shadcn-ui

shadcn-ui

热门

提供完整的 shadcn/ui 组件库模式,包括安装、配置和可访问 React 组件的实现。适用于设置 shadcn/ui、安装组件、使用 React Hook Form 和 Zod 构建表单、使用 Tailwind CSS 自定义主题,或实现按钮、对话框、下拉菜单、表格和复杂表单布局等 UI 模式。

311Star
36Fork
更新于 2026/6/22
SKILL.md
readonly只读
name
shadcn-ui
description

提供完整的 shadcn/ui 组件库模式,包括安装、配置和可访问 React 组件的实现。适用于设置 shadcn/ui、安装组件、使用 React Hook Form 和 Zod 构建表单、使用 Tailwind CSS 自定义主题,或实现按钮、对话框、下拉菜单、表格和复杂表单布局等 UI 模式。

shadcn/ui 组件模式

使用 shadcn/ui、Radix UI 和 Tailwind CSS 构建可访问、可定制的 UI 组件。

概述

  • 组件会复制到你的项目中——你拥有并可以自定义代码
  • 基于 Radix UI 原语构建,完全可访问
  • 使用 Tailwind CSS 和 CSS 变量进行主题样式设计
  • 基于 CLI 的安装:npx shadcn@latest add <component>

何时使用

当用户请求涉及以下内容时激活:

  • "设置 shadcn/ui"、"初始化 shadcn"、"添加 shadcn 组件"
  • "安装 button/input/form/dialog/card/select/toast/table/chart"
  • "React Hook Form"、"Zod 验证"、"带验证的表单"
  • "可访问组件"、"Radix UI"、"Tailwind 主题"
  • "shadcn button"、"shadcn dialog"、"shadcn sheet"、"shadcn table"
  • "暗色模式"、"CSS 变量"、"自定义主题"
  • "使用 Recharts 的图表"、"柱状图"、"折线图"、"饼图"

快速参考

可用组件

组件 安装命令 描述
button npx shadcn@latest add button 变体:default、destructive、outline、secondary、ghost、link
input npx shadcn@latest add input 文本输入字段
form npx shadcn@latest add form 集成 React Hook Form 并带验证
card npx shadcn@latest add card 包含 header、content、footer 的容器
dialog npx shadcn@latest add dialog 模态覆盖层
sheet npx shadcn@latest add sheet 滑出面板(上/右/下/左)
select npx shadcn@latest add select 下拉选择
toast npx shadcn@latest add toast 通知提示
table npx shadcn@latest add table 数据表格
menubar npx shadcn@latest add menubar 桌面风格菜单栏
chart npx shadcn@latest add chart 带主题的 Recharts 封装
textarea npx shadcn@latest add textarea 多行文本输入
checkbox npx shadcn@latest add checkbox 复选框输入
label npx shadcn@latest add label 可访问的表单标签

说明

初始化项目

# 新建 Next.js 项目
npx create-next-app@latest my-app --typescript --tailwind --eslint --app
cd my-app
npx shadcn@latest init

# 已有项目
npm install tailwindcss-animate class-variance-authority clsx tailwind-merge lucide-react
npx shadcn@latest init

# 安装组件
npx shadcn@latest add button input form card dialog select toast

基本组件用法

// 带变体和尺寸的按钮
import { Button } from "@/components/ui/button"

<Button variant="default">默认</Button>
<Button variant="destructive" size="sm">删除</Button>
<Button variant="outline" disabled>加载中...</Button>

带 Zod 验证的表单

"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("无效的邮箱"),
  password: z.string().min(8, "密码至少需要8个字符"),
})

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>邮箱</FormLabel>
            <FormControl><Input type="email" {...field} /></FormControl>
            <FormMessage />
          </FormItem>
        )} />
        <FormField name="password" control={form.control} render={({ field }) => (
          <FormItem>
            <FormLabel>密码</FormLabel>
            <FormControl><Input type="password" {...field} /></FormControl>
            <FormMessage />
          </FormItem>
        )} />
        <Button type="submit">登录</Button>
      </form>
    </Form>
  )
}

参见 references/forms-and-validation.md 了解高级多字段表单、带 API 提交的联系表单和登录卡片模式。

对话框(模态框)

import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button variant="outline">打开</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>编辑资料</DialogTitle>
    </DialogHeader>
    {/* 内容 */}
  </DialogContent>
</Dialog>

Toast 通知

// 1. 在 app/layout.tsx 中添加 <Toaster />
import { Toaster } from "@/components/ui/toaster"

// 2. 在组件中使用
import { useToast } from "@/components/ui/use-toast"

const { toast } = useToast()
toast({ title: "成功", description: "更改已保存。" })
toast({ variant: "destructive", title: "错误", description: "出错了。" })

柱状图

import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
import { ChartContainer, ChartTooltipContent } from "@/components/ui/chart"

const chartConfig = {
  desktop: { label: "桌面端", 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>

参见 references/charts-components.md 了解折线图、面积图和饼图示例。

示例

带验证的登录表单

"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("无效的邮箱"),
  password: z.string().min(8, "至少8个字符"),
})

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>邮箱</FormLabel>
            <FormControl><Input type="email" {...field} /></FormControl>
            <FormMessage />
          </FormItem>
        )} />
        <FormField name="password" control={form.control} render={({ field }) => (
          <FormItem>
            <FormLabel>密码</FormLabel>
            <FormControl><Input type="password" {...field} /></FormControl>
            <FormMessage />
          </FormItem>
        )} />
        <Button type="submit">登录</Button>
      </form>
    </Form>
  )
}

带操作的数据表格

import { 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: "姓名" },
  { accessorKey: "email", header: "邮箱" },
  { id: "actions", cell: ({ row }) => (
    <Button variant="ghost" size="sm">编辑</Button>
  )},
]

带表单的对话框

import { Button } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"

<Dialog>
  <DialogTrigger asChild>
    <Button variant="outline">添加用户</Button>
  </DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>添加新用户</DialogTitle>
    </DialogHeader>
    {/* <LoginForm /> */}
  </DialogContent>
</Dialog>

Toast 通知

import { useToast } from "@/components/ui/use-toast"
import { Button } from "@/components/ui/button"

const { toast } = useToast()

toast({ title: "已保存", description: "更改已成功保存。" })
toast({ variant: "destructive", title: "错误", description: "保存失败。" })

最佳实践

  • 可访问性:使用 Radix UI 原语——ARIA 属性已内置
  • 客户端组件:为交互式组件(hooks、事件)添加 "use client"
  • 类型安全:使用 TypeScript 和 Zod 模式进行表单验证
  • 主题:在 globals.css 中配置 CSS 变量以实现一致的设计
  • 自定义:直接修改组件文件——你拥有代码
  • 路径别名:确保在 tsconfig.json 中配置了 @ 别名
  • 注册表安全:仅从受信任的注册表安装组件;在生产使用前审查生成的代码
  • 暗色模式:使用 CSS 变量策略和 next-themes 设置
  • 表单:始终一起使用 FormFormFieldFormItemFormLabelFormMessage
  • Toaster:在根布局中添加一次 <Toaster />

约束与警告

  • 不是 NPM 包:组件被复制到你的项目中;它们不是版本化的依赖
  • 注册表安全:从 npx shadcn@latest add 获取的组件是远程获取的;在安装前始终验证注册表源是否受信任
  • 客户端组件:大多数交互式组件需要 "use client" 指令
  • Radix 依赖:确保所有 @radix-ui 包已安装
  • 需要 Tailwind:组件依赖 Tailwind CSS 工具类
  • 路径别名:在 tsconfig.json 中配置 @ 别名以用于导入

参考

查阅以下文件以获取详细模式和代码示例: