# Shadcn/UI - 构建自己的组件库
shadcn/ui (opens new window) 是一套可访问、可定制的组件和代码分发平台,它把组件源代码交给项目,让开发者构建自己的组件库。
传统组件库通常以 npm 包的形式发布。我们安装依赖、导入组件,再通过组件提供的 Props 和 CSS 覆盖样式。当设计或交互超出组件库的能力时,往往只能继续包装组件、提高 CSS 选择器优先级,或者同时引入多套 API 不一致的组件库。
shadcn/ui 要解决的就是这个问题:它不把组件实现封装在 node_modules 中,而是通过 CLI 将组件源代码复制到项目。我们可以直接修改这些代码,使组件适应自己的设计系统和业务需求。
shadcn/ui 当前版本 v4.21.0
# 与 Base UI、React Aria、Radix UI 的关系
shadcn/ui 负责组件的样式、组合方式和代码分发,Base UI、React Aria、Radix UI 则提供无样式或低样式的交互原语,比如:处理键盘操作、焦点管理、ARIA 属性和弹层定位等底层行为。
Shadcn/Create 目前支持三种 Base:
| Base | 依赖 | 说明 |
|---|---|---|
| Base UI | @base-ui/react | 面向 Web 应用和设计系统的无样式、可访问组件 |
| React Aria | react-aria-components | Adobe 提供的可访问组件和交互原语 |
| Radix UI | radix-ui | 注重开发效率、可维护性和可访问性的 UI 原语 |
选择哪一种 Base,决定 CLI 生成的组件使用哪套底层实现。它们不是同时安装的必选依赖,并且不是每个组件都依赖底层原语;Button 这类组件可能只需要普通 HTML 元素,Dialog、Select 等复杂组件才需要 Base 提供交互能力。
# 安装
对于新项目,可以先在 Shadcn/Create 中预览并生成完整配置;对于已经开始的项目,可以直接运行 shadcn CLI 初始化。
# Shadcn/Create
打开 Shadcn/Create (opens new window),可以实时预览 Style、Base Color、Theme、字体、图标和圆角等配置。这里的选择不只改变颜色,CLI 还会根据 Preset 生成对应的组件结构、样式和依赖。

# Style
Style 决定组件的整体视觉语言,包括间距、圆角、形状和排版。当前共有 8 种:
| Style | 标识符 | 说明 |
|---|---|---|
| Vega | vega | 干净、中性,接近经典 shadcn/ui 风格 |
| Nova | nova | 减少内边距和外边距 |
| Maia | maia | 圆润,并使用更宽松的间距 |
| Lyra | lyra | 方正、锐利,适合等宽字体 |
| Mira | mira | 面向高信息密度界面的紧凑风格 |
| Luma | luma | 流畅、明亮、柔和 |
| Sera | sera | 强调编辑设计和字体排版 |
| Rhea | rhea | 接近 Luma,但布局更加紧凑 |
# Base Color
Base Color 决定界面的中性色基础,例如背景、文本、边框和弱化内容的色调。当前共有 7 种:
| Base Color | 标识符 | 色调 |
|---|---|---|
| Neutral | neutral | 无明显冷暖倾向的中性灰 |
| Stone | stone | 偏暖的石灰色 |
| Zinc | zinc | 偏冷的锌灰色 |
| Mauve | mauve | 带紫色倾向的灰色 |
| Olive | olive | 带橄榄绿倾向的灰色 |
| Mist | mist | 带雾蓝倾向的灰色 |
| Taupe | taupe | 带棕色倾向的灰色 |
# Theme
Theme 决定主题颜色。除上面提到的中性色之外还有 17 种彩色:
| Theme Color | 标识符 | 色调 |
|---|---|---|
| Amber | amber | 琥珀色 |
| Blue | blue | 蓝色 |
| Cyan | cyan | 青色 |
| Emerald | emerald | 翡翠绿色 |
| Fuchsia | fuchsia | 紫红色 |
| Green | green | 绿色 |
| Indigo | indigo | 靛蓝色 |
| Lime | lime | 青柠色 |
| Orange | orange | 橙色 |
| Pink | pink | 粉色 |
| Purple | purple | 紫色 |
| Red | red | 红色 |
| Rose | rose | 玫瑰红色 |
| Sky | sky | 天蓝色 |
| Teal | teal | 蓝绿色 |
| Violet | violet | 紫罗兰色 |
| Yellow | yellow | 黄色 |
# 字体
Shadcn/Create 可以分别设置正文字体(Body)和标题字体(Heading)。标题字体可以继承正文字体,也可以单独选择;生成项目时,CLI 会安装对应字体并写入主题配置。
# Icon 库
Shadcn/Create 支持下面 5 个 Icon 库:
- Lucide (opens new window)
- Hugeicons (opens new window)
- Tabler Icons (opens new window)
- Phosphor Icons (opens new window)
- Remix Icon (opens new window)
选择 Icon 库后,CLI 会在生成组件时使用对应的图标和依赖。
# Radius
Radius 控制组件的基础圆角。Card、Input、Button 和 Popover 等组件的圆角都会根据这个值按比例计算。
| Radius | 标识符 | 值 |
|---|---|---|
| Default | default | 使用当前 Style 的默认圆角 |
| None | none | 0 |
| Small | small | 0.45rem |
| Medium | medium | 0.625rem |
| Large | large | 0.875rem |
# Menu
Menu 控制 Sidebar 等菜单区域的颜色、外观和选中状态:
| 配置项 | 选项 | 说明 |
|---|---|---|
| Color | Default | 使用当前主题的默认菜单颜色 |
| Color | Inverted | 使用与页面明暗关系相反的菜单颜色 |
| Appearance | Solid | 使用实色背景 |
| Appearance | Translucent | 使用半透明背景 |
| Accent | Subtle | 使用较弱的选中和悬停效果 |
| Accent | Bold | 使用更明显的选中和悬停效果 |
Color 和 Appearance 会组合成 default、inverted、default-translucent、inverted-translucent 四种配置。选择 Translucent 时,Accent 会固定为 Subtle,不能选择 Bold。
# 生成项目
完成配置后,点击 Get Code,可以为新项目生成初始化命令,也可以将 Preset 应用到已有项目。
# New Project
New Project 提供以下选项:
| 选项 | 说明 |
|---|---|
| Template | 选择 Next.js、Vite、TanStack Start、React Router、Laravel 或 Astro |
| Base | 选择 Base UI、React Aria 或 Radix UI |
| Use pointer on buttons | 为可用的 Button 和 role="button" 元素添加 cursor: pointer |
| Create a monorepo | 创建 Monorepo,仅支持部分 Template |
| Enable RTL support | 添加从右到左(Right-to-Left)布局支持 |
| Package Manager | 选择 pnpm、npm、yarn 或 bun |
以 pnpm、Next.js 和 Radix UI 为例,生成的命令结构如下:
$ pnpm dlx shadcn@latest init --preset <preset-code> --base radix --template next
其中 <preset-code> 是 Create 页面根据 Style、Base Color、Theme、图表颜色、字体、图标库、圆角和 Menu 等选项生成的 Preset Code。
# Existing Project
对于之前创建的 shadcn/ui 项目,可以通过 Apply Preset 修改其配置
| Apply Preset | 说明 | CLI 参数 |
|---|---|---|
| Full preset | 应用组件、主题和字体等完整 Preset | 无 |
| Theme only | 只应用颜色、圆角和阴影等主题 Token,不修改组件 | --only theme |
| Fonts only | 只应用正文和标题字体,不修改组件 | --only font |
应用完整 Preset:
$ pnpm dlx shadcn@latest apply --preset <preset-code>
如果只想修改主题:
$ pnpm dlx shadcn@latest apply --preset <preset-code> --only theme
# CLI
对于已经开始的项目,在项目根目录运行:
$ pnpm dlx shadcn@latest init
CLI 会检查当前框架和 Tailwind CSS 配置,通过交互式问题确定组件 Base、样式和颜色,然后完成以下工作:
- 创建
components.json,记录样式、Tailwind CSS 文件、Base Color、图标库和路径别名。 - 创建包含
cn函数的工具文件。 - 在全局 CSS 中配置主题变量。
- 安装组件需要的依赖。
components.json 是 shadcn CLI 的配置文件。后续执行 add、apply、migrate 等命令时,CLI 会通过它确定组件保存位置和生成方式。下面是其中最重要的配置:
{
"style": "radix-nova",
"tailwind": {
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true
},
"iconLibrary": "lucide",
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui"
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# components.json
components.json 各配置项的作用如下:
| 配置项 | 类型或可选值 | 说明 |
|---|---|---|
$schema | URL | 指定 JSON Schema,用于校验配置和提供编辑器提示 |
style | radix-*、base-*、aria-* | 组件使用的 Base 和 Style,例如 radix-nova |
tailwind.config | 路径 | Tailwind CSS 配置文件路径;Tailwind CSS v4 项目留空 |
tailwind.css | 路径 | 导入 Tailwind CSS 的全局 CSS 文件路径 |
tailwind.baseColor | neutral、stone、zinc、mauve、olive、mist、taupe | 生成默认主题 Token 时使用的 Base Color |
tailwind.cssVariables | true、false | 是否使用 CSS Variables 生成语义化主题 Token |
tailwind.prefix | 字符串 | 为生成的 Tailwind CSS Utility Class 添加前缀 |
rsc | true、false | 是否支持 React Server Components;启用后 CLI 会为客户端组件添加 use client |
tsx | true、false | 生成 .tsx TypeScript 组件,或 .jsx JavaScript 组件 |
iconLibrary | lucide、hugeicons、tabler、phosphor、remixicon | 生成组件时使用的 Icon 库 |
aliases.components | 组件路径 | Components 的导入路径 |
aliases.utils | 工具类路径 | cn 等 Utility Function 的导入路径 |
aliases.ui | UI组件路径 | UI 组件的导入路径和生成目录 |
aliases.lib | 库路径 | format-date、generate-id 等通用函数的导入路径 |
aliases.hooks | hook 路径 | use-media-query 等 Hooks 的导入路径 |
menuColor | default、inverted、default-translucent、inverted-translucent | Menu 的颜色和背景外观 |
menuAccent | subtle、bold | Menu 选中和悬停状态的强调程度 |
rtl | true、false | 是否生成支持从右到左布局的组件 |
registries | 对象 | 配置带命名空间的公共或私有 Registry |
# 主题
shadcn/ui 推荐使用 CSS Variables 管理主题。组件不直接依赖具体颜色,而是使用 background、foreground、primary、muted 等语义化 Token:
<div className="bg-background text-foreground">
<button className="bg-primary text-primary-foreground">保存</button>
</div>
2
3
全局 CSS 会分别在 :root 和 .dark 中定义亮色与暗色主题:
:root {
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.922 0 0);
--primary-foreground: oklch(0.205 0 0);
}
2
3
4
5
6
7
8
9
10
11
12
13
primary 和 primary-foreground 是一组 Token:前者控制背景,后者控制该背景上的文字和图标。
Card、Popover、Secondary、Muted、Accent 和 Sidebar 也使用相同的命名规则。
在根元素上添加 dark class 后,组件会自动使用 .dark 中的变量。因此切换暗色模式的本质,是控制根元素的 class,而不是逐个修改组件样式。
在 Shadcn/Create 中点击 Get Code,切换到 Theme,可以预览并复制当前配置生成的 Theme CSS Variables。
创建项目时,CLI 会把这些变量写入 components.json 中 tailwind.css 指定的全局 CSS 文件;Vite 项目通常是 src/index.css,Next.js 项目通常是 app/globals.css 或 src/app/globals.css。
如果不想使用 CSS Variables,可以在初始化时添加 --no-css-variables:
$ pnpm dlx shadcn@latest init --no-css-variables
这时 CLI 会把具体的 Tailwind CSS 颜色类写入组件。
# 组件
# 添加组件
使用 add 命令把组件及其依赖添加到项目:
# 添加一个组件
$ pnpm dlx shadcn@latest add button
# 一次添加多个组件
$ pnpm dlx shadcn@latest add button dialog input
2
3
4
5
生成的文件通常位于 components/ui 或 src/components/ui,具体位置由 components.json 的 aliases.ui 决定。组件进入项目后就是普通的 TypeScript 和 React 代码,可以直接修改:
import { Button } from "@/components/ui/button";
export function SaveButton() {
return <Button>保存</Button>;
}
2
3
4
5
# 查看和更新组件
本地组件可能已经被修改过,覆盖前应该先查看上游版本与本地文件的差异:
$ pnpm dlx shadcn@latest add button --diff
确认可以覆盖后,再使用 --overwrite 重新添加:
$ pnpm dlx shadcn@latest add button --overwrite
--overwrite 会覆盖本地组件代码,不会自动合并我们已经做过的修改,因此更新前最好先提交代码或保存差异。
# 删除组件
shadcn CLI 没有 remove 命令。因为组件源代码已经属于项目,删除组件时直接删除对应文件,再移除只被该组件使用的依赖即可。删除前应该先搜索组件的导入位置,避免留下失效引用。
# References
- shadcn/ui - Introduction (opens new window)
- Shadcn/Create (opens new window)
- shadcn CLI (opens new window)
- Theming (opens new window)
components.json(opens new window)- Base UI (opens new window)
- React Aria Components (opens new window)
- Radix Primitives (opens new window)
- Lucide (opens new window)
- Hugeicons (opens new window)
- Tabler Icons (opens new window)
- Phosphor Icons (opens new window)
- Remix Icon (opens new window)