Skip to content

shadcn/ui(常被口头叫 shad/ui)基础知识速览,偏向前端工程实战,适合已经会 React + Tailwind 的开发者快速上手。

一、shadcn/ui 是什么?

shadcn/ui ≠ 组件库

它是一个 组件源码集合 + CLI 工具

核心特点:

  • 不是 npm 安装的黑盒组件
  • ✅ 组件代码直接复制到你项目中
  • ✅ 基于 Radix UI(无样式、可访问性强)
  • ✅ 使用 Tailwind CSS 写样式
  • ✅ 高度可定制、可维护

一句话:

你拥有组件,而不是依赖组件库

二、核心技术栈

技术作用
React组件系统
Radix UI无障碍交互逻辑(Dialog / Dropdown / Popover 等)
Tailwind CSS样式系统
class-variance-authority(CVA)组件变体管理
lucide-react默认图标
clsx + tailwind-mergeclassName 合并

三、安装与初始化(核心流程)

bash
npx shadcn@latest init

会做的事:

  1. 检测你是否有 Tailwind

  2. 生成配置文件 components.json

  3. 创建目录:

    components/
      ui/
    lib/
      utils.ts

四、组件是怎么来的?

bash
npx shadcn@latest add button

结果:

components/ui/button.tsx

👉 源码直接进你项目

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",
        outline: "border border-input bg-background",
      },
      size: {
        sm: "h-9 px-3",
        lg: "h-11 px-8",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "sm",
    },
  }
)

五、CVA(核心重点)

shadcn/ui 的灵魂

1️⃣ 为什么不用一堆 className?

❌ 坏方式:

tsx
<button className={`
  px-4 py-2
  ${primary && "bg-blue-500"}
  ${size === "lg" && "text-lg"}
`} />

✅ shadcn/ui:

tsx
<Button variant="outline" size="lg" />

2️⃣ CVA 原理

ts
const buttonVariants = cva(
  "inline-flex items-center justify-center rounded-md font-medium",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground",
        outline: "border border-input",
        ghost: "hover:bg-accent",
      },
      size: {
        sm: "h-9 px-3",
        md: "h-10 px-4",
        lg: "h-11 px-8",
      },
    },
    defaultVariants: {
      variant: "default",
      size: "md",
    },
  }
)

最终:

ts
buttonVariants({ variant: "outline", size: "lg" })

六、Radix UI 的作用

Radix 提供的是:

  • 键盘可访问性
  • 焦点管理
  • ARIA
  • 行为逻辑

比如 Dialog:

tsx
<Dialog>
  <DialogTrigger>Open</DialogTrigger>
  <DialogContent>
    <DialogHeader>
      <DialogTitle>Title</DialogTitle>
    </DialogHeader>
  </DialogContent>
</Dialog>

shadcn/ui 做的事:

  • 给 Radix 组件 套 Tailwind 样式
  • 统一 API 风格

七、主题系统(CSS Variables)

shadcn/ui 不写死颜色

css
:root {
  --primary: 222.2 47.4% 11.2%;
  --primary-foreground: 210 40% 98%;
}

使用时:

tsx
bg-primary text-primary-foreground

优势:

  • 🌗 深色模式天然支持
  • 🎨 主题切换成本极低

八、常用目录结构

txt
components/
  ui/
    button.tsx
    dialog.tsx
    dropdown-menu.tsx
lib/
  utils.ts   // cn() 工具函数

utils.ts

ts
export function cn(...inputs: ClassValue[]) {
  return twMerge(clsx(inputs))
}

九、使用范式(很重要)

1️⃣ 组合而不是继承

tsx
<Button asChild>
  <Link href="/login">Login</Link>
</Button>

asChild 基于 Radix Slot

2️⃣ 不要改 UI 组件逻辑

tsx
components/ui/button.tsx

tsx
components/common/submit-button.tsx

十、适合什么项目?

  • ✅ 中大型 React / Next.js 项目
  • ✅ 设计系统 / Design System
  • ❌ 不适合“装完就用”的新手项目

十一、你学到什么程度算“会了”?

你能做到:

  • 看懂 shadcn/ui 组件源码
  • 自己写一个带 CVA 的组件
  • 基于 Radix 封装业务组件
  • 定制主题而不是改 class

十二、学习路径建议(给你一个进阶路线)

  1. 熟悉 Button / Input / Dialog 源码
  2. 学会 CVA
  3. 深入 Radix(Dialog / Popover / Dropdown)
  4. 自己封装一个组件(如:DataTable)
  5. 设计一套主题变量