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-merge | className 合并 |
三、安装与初始化(核心流程)
bash
npx shadcn@latest init会做的事:
检测你是否有 Tailwind
生成配置文件
components.json创建目录:
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
十二、学习路径建议(给你一个进阶路线)
- 熟悉 Button / Input / Dialog 源码
- 学会 CVA
- 深入 Radix(Dialog / Popover / Dropdown)
- 自己封装一个组件(如:DataTable)
- 设计一套主题变量