2.1 三种项目起点
shadcn/ui 支持所有主流 React 框架。CLI 会自动检测你的框架并适配。
# 方式 A:Next.js(App Router)
$ npx create-next-app@latest my-app
$ cd my-app && npx shadcn@latest init
# 方式 B:Vite + React
$ npm create vite@latest my-app -- --template react-ts
$ cd my-app && npx shadcn@latest init
# 方式 C:已有项目直接 init
$ npx shadcn@latest init
Next.js 的 create-next-app 可选内置 Tailwind;Vite 模板不带,需先 npm i -D tailwindcss @tailwindcss/vite(v4)并在 vite.config.ts 加插件。init 时 CLI 会提示缺什么。
2.2 init 交互项详解
- style(风格)
new-york更紧凑、图标用 lucide、阴影更实;default更宽松。选定后写入 components.json,影响后续所有 add 的组件外观。新项目推荐 new-york。- baseColor(基色)
- 中性灰阶:
zinc / slate / stone / gray / neutral。它决定 --background、--muted 等中性变量的色相。本教程主题即 zinc。 - CSS variables
- 选 yes 则颜色用 CSS 变量(
hsl(var(--primary))),便于主题切换;选 no 则直接写死 Tailwind 颜色类。强烈建议 yes。 - tailwind config 路径
- 你的
tailwind.config.ts(v3)或全局 CSS(v4)位置,CLI 需据此注入映射。 - components 别名
- 组件写入目录,默认
@/components,UI 组件落在@/components/ui。 - utils 别名
cn()所在文件,默认@/lib/utils。- React Server Components
- Next.js App Router 场景下标记是否 RSC 环境,影响组件是否加
"use client"。
2.3 components.json 全字段
// components.json
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "zinc",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}
Tailwind v4 用 CSS 里的 @theme 取代了 JS 配置文件,所以 tailwind.config 字段为空字符串,所有配置放到 css 指向的全局 CSS 里。v3 项目则填写 config 路径。
2.4 路径别名
组件都用 @/ 引用,必须在两处一致配置:
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": { "@/*": ["./src/*"] }
}
}
// vite.config.ts —— Vite 还需让打包器认识别名
import path from "path";
import react from "@vitejs/plugin-react";
import tailwindcss from "@tailwindcss/vite";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [react(), tailwindcss()],
resolve: { alias: { "@": path.resolve(__dirname, "./src") } },
});
2.5 CSS 变量注入(Tailwind v4)
init 会往全局 CSS 写入令牌。v4 使用 @import "tailwindcss" + @theme inline 桥接变量:
/* src/app/globals.css */
@import "tailwindcss";
@custom-variant dark (&:is(.dark *));
:root {
--radius: 0.625rem;
--background: oklch(1 0 0);
--foreground: oklch(0.145 0 0);
--primary: oklch(0.205 0 0);
--primary-foreground: oklch(0.985 0 0);
--border: oklch(0.922 0 0);
}
.dark {
--background: oklch(0.145 0 0);
--foreground: oklch(0.985 0 0);
--primary: oklch(0.985 0 0);
}
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--color-primary: var(--primary);
--radius-lg: var(--radius);
}
这样 bg-background、text-primary 这些工具类就映射到了你的变量,改一处变量即全局换肤(第 3 章展开)。
2.6 lib/utils.ts 的 cn()
// src/lib/utils.ts
import { clsx, type ClassValue } from "clsx";
import { twMerge } from "tailwind-merge";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
clsx 负责条件拼接(cn("p-2", isActive && "bg-primary")),twMerge 负责去重冲突(cn("p-2", "p-4") → "p-4")。第 4 章会大量用它。
2.7 暗色模式基础
shadcn 的暗色靠给 <html> 加 class="dark"。Next.js 用 next-themes 最省事:
$ npm i next-themes
// components/theme-provider.tsx
"use client";
import { ThemeProvider as NextThemesProvider } from "next-themes";
export function ThemeProvider({ children, ...props }) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider>;
}
// app/layout.tsx 里包裹
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>
没有 next-themes 也能手写:document.documentElement.classList.toggle("dark"),并把偏好存 localStorage。原理都是切换 html 上的 .dark class。
2.8 验证安装
$ npx shadcn@latest add button
# 若成功打印 "Created components/ui/button.tsx" 即配置完成
// 放一个按钮测试
import { Button } from "@/components/ui/button";
export default function App() {
return <Button>It works</Button>;
}
2.9 小结与下一步
npx shadcn init生成 components.json、注入 CSS 变量、写 cn()、配路径别名。- Tailwind v4 用 CSS 里的
@theme,v3 用 JS config——CLI 会自动适配。 - 暗色模式统一靠 html 上的
.darkclass,Next 用 next-themes 最方便。 - 下一章深入主题与设计令牌——把 CSS 变量玩成一套可自由换肤的设计系统。