返回首页
🎨 前端 / Web
shadcn/ui + 设计系统 2026:现代 Web 产品的 UI 实战
shadcn/ui 是 2026 年最火的前端组件库 + 设计系统方案。本文从 0 到完整设计系统,含 5 个真实项目 + 主题定制 + 组件库扩展 + A11y。
shadcn/ui · 设计系统 · Tailwind v4 · Radix UI · 前端 · UI 设计 · 设计令牌
📰
今日技术简讯
📰 技术简讯 · 2026-07-30
今日聚合 6 条热门技术内容(中文素材优先)。
🤖 AI / LLM
1. Figma AI 推出"自动设计系统"
- 链接:https://figma.com/ai/design-system
- 来源:Figma
- 摘要:Figma AI 自动生成完整设计系统,颜色 / 字体 / 组件 / 间距全部自动建议。
2. v0.dev 推出 shadcn/ui 模板市场
- 链接:https://v0.dev/shadcn-templates
- 来源:Vercel
- 摘要:v0.dev 推出 shadcn/ui 模板市场,200+ SaaS 模板,30 秒生成完整 UI。
🎨 前端 / Web
3. shadcn/ui 推出 2026 路线图
- 链接:https://ui.shadcn.com/docs/roadmap
- 来源:shadcn
- 摘要:shadcn/ui 2026 推出 Tailwind v4 + 完整 A11y + 设计令牌 + 多主题。
4. Radix UI 推出 Themes 2.0
- 链接:https://radix-ui.com/themes
- 来源:Radix
- 摘要:Radix Themes 2.0 推出完整设计系统,颜色 / 字体 / 圆角 / 阴影全面可定制。
⚙️ 后端 / 架构
5. Tailwind v4 GA
- 链接:https://tailwindcss.com/blog/v4
- 来源:Tailwind Labs
- 摘要:Tailwind v4 GA,CSS-first 配置(无 JS),性能 +5x,CSS 体积 -50%。
🚀 独立开发 / OPC
6. 即刻"shadcn/ui 设计系统"专题
- 链接:https://m.okjike.com/shadcn-design-system
- 来源:即刻
- 摘要:即刻 200+ 独立开发者分享 shadcn/ui 实战经验,主题 / 组件 / 模板市场。
数据来源:掘金 / InfoQ 中文 / 即刻 / 少数派 / HN 采集时间:2026-07-30 09:00 (UTC+8)
📝
今日深度文
shadcn/ui + 设计系统 2026:现代 Web 产品的 UI 实战
一句话结论:shadcn/ui + Tailwind v4 = 2026 年前端 UI 终极方案。无头组件 + 复制即用 + 完全可控 + 设计令牌统一。本文从 0 到完整设计系统。
背景
shadcn/ui 是 2026 年最火的前端组件库,GitHub 60K+ stars:
- 不是传统组件库:复制源码到项目,完全可控
- 基于 Radix UI:完全可访问(A11y)
- 基于 Tailwind:原子化样式
- TypeScript 原生:完整类型支持
为什么 shadcn/ui 取代 MUI / Ant Design:
| 维度 | shadcn/ui | MUI | Ant Design |
|---|---|---|---|
| Bundle | 0 | 200KB | 500KB |
| 定制 | 完全 | 中等 | 困难 |
| A11y | 优秀 | 优秀 | 中等 |
| 设计 | 现代 | Material | 传统 |
| 学习曲线 | 低 | 中 | 高 |
6 大核心优势
1. 复制即用,无依赖
# ✅ shadcn/ui
npx shadcn@latest add button
# 自动复制 Button.tsx 到项目,完全可控
# ❌ MUI / Ant
npm install @mui/material
# 引入整个库,难定制
2. 完全可控的源码
// shadcn/ui 生成的 Button.tsx(在项目中)
// 你可以随意修改
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
"inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, ...props }, ref) => {
const Comp = asChild ? Slot : "button";
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
{...props}
/>
);
}
);
Button.displayName = "Button";
export { Button, buttonVariants };
3. 完全可访问(A11y)
// shadcn/ui 基于 Radix UI
// 自动支持:
// - 键盘导航(Tab / Shift+Tab / Enter / Esc)
// - 屏幕阅读器(ARIA 标签)
// - 焦点管理
// - 国际化
// 示例:Dialog
import { Dialog } from "@/components/ui/dialog";
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>提示</DialogTitle>
</DialogHeader>
<DialogDescription>
你确定要删除这个项目吗?
</DialogDescription>
<DialogFooter>
<Button variant="outline">取消</Button>
<Button variant="destructive">删除</Button>
</DialogFooter>
</DialogContent>
</Dialog>
4. 完美集成 React 19(与 7/22 关联)
// shadcn/ui + React Server Components
// components/ui/button.tsx(Client Component)
"use client";
import * as React from "react";
// ...
// app/page.tsx(Server Component)
import { Button } from "@/components/ui/button";
export default function Page() {
return (
<Button onClick={() => alert("Hi")}>
Click me
</Button>
);
}
5. 设计令牌系统
/* globals.css */
@layer base {
:root {
/* 颜色 */
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
/* ... */
/* 字体 */
--font-sans: ui-sans-serif, system-ui, sans-serif;
--font-mono: ui-monospace, monospace;
/* 圆角 */
--radius: 0.5rem;
}
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... */
}
}
6. Tailwind v4 集成(与 7/22 关联)
/* app.css - Tailwind v4 CSS-first 配置 */
@import "tailwindcss";
@theme {
--color-primary: hsl(222.2 47.4% 11.2%);
--color-primary-foreground: hsl(210 40% 98%);
/* ... */
}
5 个实战项目
项目 1:SaaS Dashboard
// app/dashboard/page.tsx
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Badge } from "@/components/ui/badge";
export default function DashboardPage() {
return (
<div className="grid grid-cols-1 md:grid-cols-3 gap-4 p-6">
{/* 数据卡片 */}
<Card>
<CardHeader>
<CardTitle>总用户数</CardTitle>
</CardHeader>
<CardContent>
<p className="text-3xl font-bold">12,345</p>
<Badge variant="success" className="mt-2">+12%</Badge>
</CardContent>
</Card>
{/* 图表 */}
<Card className="col-span-2">
<CardHeader>
<CardTitle>用户增长</CardTitle>
</CardHeader>
<CardContent>
<LineChart data={data} />
</CardContent>
</Card>
{/* 最近活动 */}
<Card className="md:col-span-3">
<CardHeader>
<CardTitle>最近活动</CardTitle>
</CardHeader>
<CardContent>
<Tabs defaultValue="all">
<TabsList>
<TabsTrigger value="all">全部</TabsTrigger>
<TabsTrigger value="users">用户</TabsTrigger>
<TabsTrigger value="orders">订单</TabsTrigger>
</TabsList>
<TabsContent value="all">
<ActivityList />
</TabsContent>
</Tabs>
</CardContent>
</Card>
</div>
);
}
项目 2:登录 / 注册页
// app/login/page.tsx
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card";
export default function LoginPage() {
return (
<div className="flex items-center justify-center min-h-screen">
<Card className="w-[400px]">
<CardHeader>
<CardTitle>登录</CardTitle>
<CardDescription>使用邮箱登录</CardDescription>
</CardHeader>
<CardContent>
<form action={login}>
<div className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email">邮箱</Label>
<Input id="email" name="email" type="email" required />
</div>
<div className="space-y-2">
<Label htmlFor="password">密码</Label>
<Input id="password" name="password" type="password" required />
</div>
<Button type="submit" className="w-full">登录</Button>
</div>
</form>
</CardContent>
<CardFooter>
<p className="text-sm text-muted-foreground">
还没有账号?<a href="/signup" className="text-primary">注册</a>
</p>
</CardFooter>
</Card>
</div>
);
}
项目 3:数据表格
// components/data-table.tsx
"use client";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { ArrowUpDown } from "lucide-react";
export function DataTable({ data }: { data: User[] }) {
return (
<div className="rounded-md border">
<Table>
<TableHeader>
<TableRow>
<TableHead>
<Button variant="ghost" onClick={() => sort('name')}>
姓名 <ArrowUpDown className="ml-2 h-4 w-4" />
</Button>
</TableHead>
<TableHead>邮箱</TableHead>
<TableHead>角色</TableHead>
<TableHead>创建时间</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{data.map((user) => (
<TableRow key={user.id}>
<TableCell className="font-medium">{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
<TableCell>{user.role}</TableCell>
<TableCell>{user.createdAt.toLocaleDateString()}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</div>
);
}
项目 4:完整 SaaS UI(多页)
src/
├── app/
│ ├── (marketing)/ # 营销页(公开)
│ │ ├── page.tsx # Landing
│ │ ├── pricing/page.tsx
│ │ └── about/page.tsx
│ ├── (auth)/ # 认证(公开)
│ │ ├── login/page.tsx
│ │ └── signup/page.tsx
│ ├── (dashboard)/ # 仪表板(认证)
│ │ ├── dashboard/page.tsx
│ │ ├── projects/page.tsx
│ │ ├── settings/page.tsx
│ │ └── billing/page.tsx
│ └── (admin)/ # 管理(管理员)
│ └── admin/page.tsx
└── components/
├── ui/ # shadcn 组件
├── marketing/ # 营销组件
├── dashboard/ # 仪表板组件
└── admin/ # 管理组件
项目 5:主题定制(多品牌)
// app/layout.tsx
import { ThemeProvider } from "@/components/theme-provider";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="zh" suppressHydrationWarning>
<body>
<ThemeProvider
attribute="class"
defaultTheme="system"
enableSystem
disableTransitionOnChange
>
{children}
</ThemeProvider>
</body>
</html>
);
}
// 切换主题
"use client";
import { useTheme } from "next-themes";
import { Moon, Sun } from "lucide-react";
export function ThemeToggle() {
const { theme, setTheme } = useTheme();
return (
<Button
variant="ghost"
size="icon"
onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
>
<Sun className="h-5 w-5 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-5 w-5 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
</Button>
);
}
5 个常见坑
坑 1:组件修改不生效
// ❌ 直接修改 node_modules/shadcn/...(不可行)
// ✅ shadcn/ui 是源码复制,修改项目里的文件即可
坑 2:图标库选择
// ✅ 推荐:lucide-react(Tree-shakeable)
import { ChevronDown } from "lucide-react";
// ❌ 避免:react-icons(体积大)
坑 3:表单处理
// ✅ 推荐:react-hook-form + zod
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
const schema = z.object({
email: z.string().email(),
password: z.string().min(8),
});
const { register, handleSubmit, formState: { errors } } = useForm({
resolver: zodResolver(schema),
});
坑 4:深色主题
// ❌ 忘记 suppressHydrationWarning
<html>...</html>
// ✅ 加上
<html suppressHydrationWarning>
坑 5:Server Components 限制
// ❌ useState 不能在 Server Component 用
export default function Page() {
const [open, setOpen] = useState(false); // ❌
}
// ✅ 加 "use client"
"use client";
export default function Page() {
const [open, setOpen] = useState(false); // ✅
}
性能对比
| 方案 | Bundle | 定制 | 学习曲线 |
|---|---|---|---|
| shadcn/ui | 0 | 完全 | 低 |
| MUI | 200KB | 中 | 中 |
| Ant Design | 500KB | 困难 | 高 |
| Chakra UI | 150KB | 中 | 中 |
shadcn/ui 优势:
- 0 Bundle:只复制用到的组件
- 完全定制:源码在你手里
- 现代设计:基于 Tailwind v4
- A11y 优秀:基于 Radix UI
与之前内容的关系
7/16 TypeScript 5.6 → 前端基础
7/22 React 19 RSC → 前端框架
7/24 Cursor + Claude Code → 编程工具
7/29 WebGPU → 前沿技术
7/30 shadcn/ui 设计系统 → UI / 设计 ← 今天
→ "基础 → 框架 → 工具 → 前沿 → 设计"完整闭环
7 天落地路径
Day 1:初始化 shadcn/ui
npx create-next-app@latest my-app
cd my-app
npx shadcn@latest init
Day 2:添加核心组件
npx shadcn@latest add button card input label
npx shadcn@latest add dialog dropdown-menu tabs
Day 3:设计令牌
/* globals.css */
@layer base {
:root {
--primary: 222.2 47.4% 11.2%;
/* ... */
}
}
Day 4:深色主题
<ThemeProvider attribute="class" defaultTheme="system" />
Day 5:表单 + 验证
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
Day 6:扩展组件
// 自定义组件:基于 shadcn/ui
<DataTable columns={columns} data={data} />
Day 7:部署
# Vercel(关联 7/18)
vercel --prod
我的看法
shadcn/ui 是 2026 年前端 UI 的"终极方案":
- 0 Bundle:只复制用到的
- 完全可控:源码在项目里
- A11y 优秀:基于 Radix UI
- 现代设计:基于 Tailwind v4
- 完美集成:React 19 + RSC
对独立开发者的建议:
- 新项目首选:替代 MUI / Ant Design
- 快速原型:v0 + shadcn 模板
- 设计系统:统一令牌 + 组件
- 多主题:内置深色模式
参考
- shadcn/ui 官方
- Radix UI
- Tailwind CSS v4
- Lucide Icons
- v0.dev
- TypeScript 5.6(7/16)
- React 19 RSC(7/22)
- Cursor + Claude Code(7/24)
- Vercel + Cloudflare(7/18)
本文基于 shadcn/ui 2026 + Tailwind v4,2026 年 7 月最新实战。
📚 同主题文章
🎨前端 / Web·
React 19 实战:从 Server Components 到 Server Actions 完整指南
React 19 是前端框架的"分水岭"——Server Components 让前端从"CSR + API"转向"RSC + Actions"。本文从 0 到生产级 RSC 实战,含 4 个真实项目 + 性能对比。
ReactServer ComponentsServer Actions
🎨前端 / Web·
TypeScript 5.6 实战:从入门到生产级类型系统
TypeScript 5.6 引入 infer const / iterator helpers 等重磅特性。本文从基础到生产级类型系统实战,含 4 个真实项目 + 类型设计模式。
TypeScript类型系统前端
🎨前端 / Web·
React Native vs Flutter 2026 对比:跨平台框架选型
React Native 0.78 与 Flutter 4.5 是 2026 年跨平台移动开发的两个主流选择。本文用真实项目数据对比两者。
React NativeFlutter跨平台