⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

3.4.2 复制粘贴就能用的组件——shadcn/ui

一句话破题

shadcn/ui 不是 npm 包,而是可复制到项目中的高质量组件代码,你拥有完全控制权。

核心价值

传统组件库(如 Ant Design、MUI)是黑盒——你用它们的组件,按它们的规则定制。shadcn/ui 不同:组件代码直接复制到你的项目中,你可以随意修改。

shadcn/ui vs 传统组件库

特性shadcn/ui传统组件库
安装方式复制代码到项目npm install
定制性完全可控受限于 API
更新方式手动更新npm update
体积只包含使用的可能引入多余代码
学习成本低(标准 React)需学习特定 API

快速开始

1. 初始化

bash
npx shadcn@latest init

选择配置:

  • Style: Default
  • Base color: Slate
  • CSS variables: Yes

2. 添加组件

bash
# 添加单个组件
npx shadcn@latest add button

# 添加多个组件
npx shadcn@latest add card input label

# 查看所有可用组件
npx shadcn@latest add

3. 使用组件

tsx
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
import { Input } from "@/components/ui/input"

export function LoginForm() {
  return (
    <Card className="w-[400px]">
      <CardHeader>
        <CardTitle>登录</CardTitle>
      </CardHeader>
      <CardContent className="space-y-4">
        <Input placeholder="邮箱" type="email" />
        <Input placeholder="密码" type="password" />
        <Button className="w-full">登录</Button>
      </CardContent>
    </Card>
  )
}

常用组件速览

组件用途安装命令
Button按钮add button
Input输入框add input
Card卡片容器add card
Dialog弹窗add dialog
Select下拉选择add select
Table表格add table
Form表单(含验证)add form
Toast提示消息add toast

组件变体

shadcn/ui 组件通常提供多种变体:

tsx
// Button 变体
<Button variant="default">默认</Button>
<Button variant="secondary">次要</Button>
<Button variant="outline">描边</Button>
<Button variant="ghost">幽灵</Button>
<Button variant="destructive">危险</Button>

// 尺寸
<Button size="sm">小</Button>
<Button size="default">中</Button>
<Button size="lg">大</Button>

定制组件

组件代码在 components/ui/ 目录下,可直接修改:

tsx
// components/ui/button.tsx
const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md text-sm font-medium...",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        // 添加自定义变体
        brand: "bg-brand-500 text-white hover:bg-brand-600",
      },
      // ...
    },
  }
)

cn() 工具函数

shadcn/ui 使用 cn() 合并类名:

tsx
import { cn } from "@/lib/utils"

// 合并默认类和自定义类
<Button className={cn("w-full", isLoading && "opacity-50")}>
  提交
</Button>

表单集成

shadcn/ui 的 Form 组件与 react-hook-form 深度集成:

bash
npx shadcn@latest add form
tsx
import { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import { z } from "zod"
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form"

const formSchema = z.object({
  email: z.string().email("请输入有效的邮箱"),
  password: z.string().min(6, "密码至少6位"),
})

export function LoginForm() {
  const form = useForm<z.infer<typeof formSchema>>({
    resolver: zodResolver(formSchema),
  })

  function onSubmit(values: z.infer<typeof formSchema>) {
    console.log(values)
  }

  return (
    <Form {...form}>
      <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
        <FormField
          control={form.control}
          name="email"
          render={({ field }) => (
            <FormItem>
              <FormLabel>邮箱</FormLabel>
              <FormControl>
                <Input placeholder="your@email.com" {...field} />
              </FormControl>
              <FormMessage />
            </FormItem>
          )}
        />
        <Button type="submit">登录</Button>
      </form>
    </Form>
  )
}

AI 协作指南

核心意图:让 AI 使用 shadcn/ui 组件构建 UI。

需求定义公式

  • 功能描述:我需要一个 [功能] 界面
  • 组件要求:使用 shadcn/ui 的 [组件列表]
  • 样式要求:[额外的 Tailwind 类]

关键术语shadcn/uivariantcn()Formreact-hook-form

交互策略

  1. 先确认需要哪些 shadcn 组件
  2. 让 AI 生成使用这些组件的代码
  3. 如需表单验证,指定使用 Form + zod

避坑指南

  1. 先安装再使用:组件不会自动安装,需要手动 add
  2. 路径别名:确保 @/components/ui 路径正确配置
  3. 依赖关系:某些组件依赖其他组件,会自动一起安装
  4. 暗色模式:需要在 layout.tsx 中配置 ThemeProvider

验收清单

  • [ ] 组件正确安装到 components/ui/
  • [ ] 导入路径使用 @/components/ui/xxx
  • [ ] 使用 cn() 合并额外的类名
  • [ ] 表单使用 Form 组件并配置验证