重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
shadcn by vercel-labs/vercel-plugin
npx skills add https://github.com/vercel-labs/vercel-plugin --skill shadcn您是 shadcn/ui 方面的专家——这是一套基于 Radix UI 原语和 Tailwind CSS 构建的、设计精美、可访问且可自定义的 React 组件集合。组件会作为源代码直接添加到您的代码库中,而不是作为依赖项安装。
shadcn/ui 不是传统意义上的组件库。您不会将其作为软件包安装。相反,CLI 会将组件源代码复制到您的项目中,让您拥有完全的所有权和自定义能力。
重要提示:shadcn init 默认是交互式的。对于非交互式初始化,请始终使用 -d(默认值):
# 使用默认值进行非交互式初始化 — 请使用此命令
npx shadcn@latest init -d
# 使用预设进行非交互式初始化(推荐用于一致的设计系统)
npx shadcn@latest init --preset <code> -f
# 明确选择基础库的非交互式初始化
npx shadcn@latest init -d --base radix
npx shadcn@latest init -d --base base-ui
# 搭建完整的项目模板(CLI v4)
AI Elements 兼容性:当项目使用或可能使用 AI Elements 时,请始终使用
--base radix(默认值)。AI Elements 组件依赖 Radix API,与 Base UI 一起使用会出现类型错误。
npx shadcn@latest init --template next -d
npx shadcn@latest init --template vite -d
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
选项:
-d, --defaults — 使用默认配置,跳过所有交互式提示(CI/代理使用所必需)-y, --yes — 跳过确认提示(不会跳过库选择 — 请改用 -d)-f, --force — 强制覆盖现有配置-t, --template — 搭建完整的项目模板(next、vite、react-router、astro、laravel、tanstack-start)--preset — 应用一个设计系统预设(颜色、主题、图标、字体、圆角半径)作为单一可共享代码--base — 选择基础库:radix(默认)或 base-ui--monorepo — 设置 monorepo 结构警告:单独使用
-y/--yes并不能使 init 完全非交互式 — 它仍然会提示选择组件库。请始终使用-d来跳过所有提示。
CLI v4 中已弃用:
--style、--base-color、--src-dir、--no-base-style和--css-variables标志已被移除,使用会报错。registry:build和registry:mcp注册表类型也已弃用。请改用registry:base和registry:font。
初始化命令会:
components.json 配置文件cn() 工具函数# 添加特定组件
npx shadcn@latest add button dialog card
# 添加所有可用组件
npx shadcn@latest add --all
# 从自定义注册表添加
npx shadcn@latest add @v0/dashboard
npx shadcn@latest add @acme/custom-button
# 从 AI Elements 注册表添加
npx shadcn@latest add https://elements.ai-sdk.dev/api/registry/all.json
选项:
-o, --overwrite — 覆盖现有文件-p, --path — 自定义安装路径-a, --all — 安装所有组件--dry-run — 预览将要添加的内容而不写入文件--diff — 更新现有组件时显示更改差异--view — 内联显示注册表项的源代码npx shadcn@latest search button
npx shadcn@latest list @v0
npx shadcn@latest build
npx shadcn@latest build ./registry.json -o ./public/r
# 在安装前查看注册表项的源代码
npx shadcn@latest view button
# 显示项目诊断信息 — 配置、已安装组件、依赖项
npx shadcn@latest info
# 获取任何组件的文档、代码和示例(代理友好输出)
npx shadcn@latest docs button
npx shadcn@latest docs dialog
shadcn docs为编码代理提供了正确使用原语的上下文 — 返回内联的代码示例、API 参考和使用模式。
npx shadcn@latest migrate rtl # RTL 支持迁移
npx shadcn@latest migrate radix # 迁移到统一的 radix-ui 包
npx shadcn@latest migrate icons # 图标库变更
# 迁移默认 ui 目录之外的组件
npx shadcn@latest migrate radix src/components/custom
shadcn/skills 为编码代理提供了正确使用组件和注册表所需的上下文。它涵盖了 Radix 和 Base UI 原语、更新的 API、组件模式和注册表工作流。该技能知道如何使用 CLI、何时调用它以及传递哪些标志 — 因此代理生成的代码能与您的设计系统匹配。
安装:pnpm dlx skills add shadcn/ui
new-york 样式现在使用单一的 radix-ui 包,而不是单独的 @radix-ui/react-* 包:
// 旧版 — 单独的包
import * as DialogPrimitive from "@radix-ui/react-dialog"
// 新版 — 统一的包
import { Dialog as DialogPrimitive } from "radix-ui"
要迁移现有项目:npx shadcn@latest migrate radix。迁移后,从 package.json 中移除未使用的 @radix-ui/react-* 包。
shadcn/ui 现在支持 Base UI 作为底层原语库的替代方案。无论您选择哪个库,组件的外观和行为都相同 — 只有底层实现会改变。
在初始化时选择:npx shadcn@latest init --base base-ui
CLI 会根据您的项目配置自动拉取正确的组件变体。
components.json 文件配置了 shadcn/ui 在您项目中的工作方式:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "zinc", // 选项:gray, neutral, slate, stone, zinc, mauve, olive, mist, taupe
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {
"v0": {
"url": "https://v0.dev/chat/api/registry"
},
"ai-elements": {
"url": "https://elements.ai-sdk.dev/api/registry"
}
}
}
为您的项目配置多个注册表:
{
"registries": {
"acme": {
"url": "https://acme.com/registry/{name}.json"
},
"private": {
"url": "https://internal.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
使用命名空间语法安装:
npx shadcn@latest add @acme/header @private/auth-form
shadcn/ui 使用 CSS 自定义属性进行主题化,定义在 globals.css 中:
@theme inline {
--color-background: oklch(0.145 0 0);
--color-foreground: oklch(0.985 0 0);
--color-card: oklch(0.205 0 0);
--color-card-foreground: oklch(0.985 0 0);
--color-primary: oklch(0.488 0.243 264.376);
--color-primary-foreground: oklch(0.985 0 0);
--color-secondary: oklch(0.269 0 0);
--color-secondary-foreground: oklch(0.985 0 0);
--color-muted: oklch(0.269 0 0);
--color-muted-foreground: oklch(0.708 0 0);
--color-accent: oklch(0.269 0 0);
--color-accent-foreground: oklch(0.985 0 0);
--color-destructive: oklch(0.396 0.141 25.723);
--color-border: oklch(0.269 0 0);
--color-input: oklch(0.269 0 0);
--color-ring: oklch(0.488 0.243 264.376);
--radius: 0.625rem;
/* CLI v4:圆角半径标记使用乘法计算而非加法 */
--radius-xs: calc(var(--radius) * 0.5);
--radius-sm: calc(var(--radius) * 0.75);
--radius-md: calc(var(--radius) * 0.875);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.5);
}
对于深色模式,在 <html> 上使用 dark 类:
// app/layout.tsx
<html lang="en" className="dark">
或者使用 next-themes 进行切换:
import { ThemeProvider } from 'next-themes'
<ThemeProvider attribute="class" defaultTheme="dark">
{children}
</ThemeProvider>
在 shadcn 默认值旁边添加应用特定的颜色:
@theme inline {
/* 上面的 shadcn 默认值... */
/* 自定义应用颜色 */
--color-priority-urgent: oklch(0.637 0.237 15.163);
--color-priority-high: oklch(0.705 0.213 47.604);
--color-status-done: oklch(0.723 0.219 149.579);
}
在组件中使用:
<span className="text-[var(--color-priority-urgent)]">Urgent</span>
// 或者使用 Tailwind v4 的 theme():
<span className="text-priority-urgent">Urgent</span>
| 组件 | 使用场景 |
|---|---|
button | 操作、表单提交 |
card | 内容容器 |
dialog | 模态框、确认提示 |
input / textarea | 表单字段 |
select | 下拉选择 |
table | 数据显示 |
tabs | 视图切换 |
command | 命令面板(Cmd+K) |
dropdown-menu | 上下文菜单 |
popover | 浮动内容 |
tooltip | 悬停提示 |
badge | 状态指示器 |
avatar | 用户头像 |
scroll-area | 可滚动容器 |
separator | 视觉分隔线 |
label | 表单标签 |
sheet | 侧滑面板 |
skeleton | 加载占位符 |
shadcn/ui 不仅仅是一个组件源代码生成器。在 Vercel 技术栈中,它是默认的界面语言。不要停留在“组件能用”的阶段。要组合出感觉经过深思熟虑、信息密度高且一致的页面。
new-york 样式。--color-primary 使用一种强调色。bg-background、bg-card、text-foreground、text-muted-foreground、border-border、ring-ring。避免使用临时的十六进制值。--radius: 0.625rem 是一个很好的基准。gap-6 / p-6 / text-sm)或紧凑型(gap-4 / p-4 / text-sm)。h-4 w-4 或 h-5 w-5。| 使用场景 | 首选方案 | 原因 |
|---|---|---|
| 设置页面 | Tabs + Card + Form | 清晰的信息分组,具有可预测的保存流程 |
| 数据仪表板 | Card + Badge + Table + DropdownMenu | 涵盖摘要、状态、密集数据和行操作,无需自定义外壳 |
| CRUD 表格 | Table + DropdownMenu + Sheet + AlertDialog | 以标准模式支持浏览、操作、编辑和破坏性确认 |
| 认证界面 | Card + Label + Input + Button + Alert | 保持登录流程专注,并妥善处理错误 |
| 全局搜索 | Command + Dialog | 快速的键盘优先发现,具有成熟的交互模型 |
| 移动端导航 | Sheet + Button + Separator | 提供紧凑的导航外壳,能干净地适应小屏幕 |
| 详情页面 | header + Badge + Separator + Card | 平衡层次结构、元数据和支持内容,避免过度嵌套 |
| 筛选器 | Card 侧边栏 + Sheet + Select | 适用于持久的桌面筛选器和可折叠的移动端控件 |
| 空状态/加载/错误状态 | Card + Skeleton + Alert | 为非理想路径提供设计过的界面,而不是占位符文本 |
Tabs + 每组一个 Card + Separator + 保存操作Card + 筛选栏 + TableBadge + 主 Card + 侧边 Card + 用于破坏性操作的 AlertDialogCommand 用于快速查找,Popover 用于选择器,Sheet 用于移动端筛选器Card + 社交 Separator + 内联 Alert 用于错误AlertDialog(而非 Dialog)进行确认button / input / select / divdiv rounded-xl border p-6 而不是 Tabs / Table / Sheet / DialogDialog 进行破坏性确认而不是 AlertDialog创建您自己的组件注册表以跨项目共享:
| 类型 | 用途 |
|---|---|
registry:ui | 独立的 UI 组件 |
registry:base | 完整的设计系统负载 — 组件、依赖项、CSS 变量、字体、配置 |
registry:font | 字体配置作为一等注册表项 |
[
{
"name": "my-component",
"type": "registry:ui",
"title": "My Component",
"description": "A custom component",
"files": [
{
"path": "components/my-component.tsx",
"type": "registry:ui"
}
],
"dependencies": ["lucide-react"]
}
]
npx shadcn@latest build
# 输出到 public/r/my-component.json
npx shadcn@latest add https://your-domain.com/r/my-component.json
shadcn init 在 Next.js 中破坏 Geist 字体(Tailwind v4)shadcn init 会重写 globals.css,并可能引入 --font-sans: var(--font-sans) — 这是一个循环自引用,会破坏字体加载。Tailwind v4 的 @theme inline 在解析时解析 CSS 自定义属性,而不是运行时 — 所以即使是 var(--font-geist-sans) 也不起作用,因为 Next.js 在运行时通过 className 注入该变量。
修复方法:在 @theme inline 中使用字面量字体族名称:
/* 在 @theme inline 中 — 正确(字面量名称) */
--font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
--font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;
/* 错误 — 循环引用,解析为空 */
--font-sans: var(--font-sans);
/* 同样错误 — @theme inline 无法解析运行时 CSS 变量 */
--font-sans: var(--font-geist-sans);
运行 shadcn init 后,请务必:
@theme inline 中的字体声明替换为字面量的 Geist 字体名称(如上所示)<body> 移动到 layout.tsx 中的 <html>:// layout.tsx — 字体变量在 <html> 上,而不是 <body>
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
<body className="antialiased">
size 属性shadcn 的 Avatar 组件不接受 size 变体属性。使用 Tailwind 类来控制大小:
// 错误 — 不存在 size 变体
<Avatar size="lg" /> // ❌ TypeScript 错误 / 静默忽略
// 正确 — 使用 Tailwind
<Avatar className="h-12 w-12">
<AvatarImage src={user.image} />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
// 小头像
<Avatar className="h-6 w-6"> ... </Avatar>
这适用于大多数 shadcn 组件 — 它们使用 Tailwind 类来控制大小,而不是变体属性。如果您需要可重用的尺寸变体,请通过组件源代码中的 cva 自行添加。
所有 shadcn 组件都使用 cn() 工具函数来合并条件类:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
由于您拥有源代码,可以直接扩展组件:
// components/ui/button.tsx — 添加您的自定义变体
const buttonVariants = cva('...', {
variants: {
variant: {
default: '...',
destructive: '...',
// 添加自定义变体
success: 'bg-green-600 text-white hover:bg-green-700',
premium: 'bg-gradient-to-r from-purple-500 to-pink-500 text-white',
},
},
})
许多组件需要在根目录使用 TooltipProvider:
// app/layout.tsx
import { TooltipProvider } from '@/components/ui/tooltip'
export default function RootLayout({ children }) {
return (
<html lang="en" className="dark">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
)
}
预设将您的整个设计系统配置(颜色、主题、图标库、字体、圆角半径)捆绑到一个单一的可共享代码中。一个字符串即可配置所有内容:
# 在初始化时应用预设
npx shadcn@latest init --preset <code>
# 在现有项目中切换预设(重新配置所有内容,包括组件)
npx shadcn@latest init --preset <code>
在 shadcn/create 上构建自定义预设 — 在发布前预览颜色、字体和圆角半径如何应用于真实组件。
CLI 在安装时处理 RTL 转换:
npx shadcn@latest migrate rtl
自动将方向性类(ml-4、left-2)转换为逻辑属性(ms-4、start-2)。
每周安装量
63
仓库
GitHub 星标数
88
首次出现
2026 年 3 月 7 日
安全审计
安装于
opencode61
codex61
gemini-cli60
cursor60
github-copilot60
amp60
You are an expert in shadcn/ui — a collection of beautifully designed, accessible, and customizable React components built on Radix UI primitives and Tailwind CSS. Components are added directly to your codebase as source code, not installed as a dependency.
shadcn/ui is not a component library in the traditional sense. You don't install it as a package. Instead, the CLI copies component source code into your project, giving you full ownership and customization ability.
IMPORTANT : shadcn init is interactive by default. Always use -d (defaults) for non-interactive initialization:
# Non-interactive init with defaults — USE THIS
npx shadcn@latest init -d
# Non-interactive with a preset (recommended for consistent design systems)
npx shadcn@latest init --preset <code> -f
# Non-interactive with explicit base library choice
npx shadcn@latest init -d --base radix
npx shadcn@latest init -d --base base-ui
# Scaffold a full project template (CLI v4)
AI Elements compatibility : Always use
--base radix(the default) when the project uses or may use AI Elements. AI Elements components rely on Radix APIs and have type errors with Base UI.
npx shadcn@latest init --template next -d
npx shadcn@latest init --template vite -d
Options:
-d, --defaults — Use default configuration, skip all interactive prompts (REQUIRED for CI/agent use)-y, --yes — Skip confirmation prompts (does NOT skip library selection — use -d instead)-f, --force — Force overwrite existing configuration-t, --template — Scaffold full project template (next, vite, react-router, astro, laravel, )WARNING :
-y/--yesalone does NOT make init fully non-interactive — it still prompts for component library selection. Always use-dto skip ALL prompts.
Deprecated in CLI v4 :
--style,--base-color,--src-dir,--no-base-style, and--css-variablesflags are removed and will error. Theregistry:buildandregistry:mcpregistry types are also deprecated. Useregistry:baseandregistry:fontinstead.
The init command:
components.json configurationcn() utility function# Add specific components
npx shadcn@latest add button dialog card
# Add all available components
npx shadcn@latest add --all
# Add from a custom registry
npx shadcn@latest add @v0/dashboard
npx shadcn@latest add @acme/custom-button
# Add from AI Elements registry
npx shadcn@latest add https://elements.ai-sdk.dev/api/registry/all.json
Options:
-o, --overwrite — Overwrite existing files-p, --path — Custom install path-a, --all — Install all components--dry-run — Preview what will be added without writing files--diff — Show diff of changes when updating existing components--view — Display a registry item's source code inlinenpx shadcn@latest search button
npx shadcn@latest list @v0
npx shadcn@latest build
npx shadcn@latest build ./registry.json -o ./public/r
# View a registry item's source before installing
npx shadcn@latest view button
# Show project diagnostics — config, installed components, dependencies
npx shadcn@latest info
# Get docs, code, and examples for any component (agent-friendly output)
npx shadcn@latest docs button
npx shadcn@latest docs dialog
shadcn docsgives coding agents the context to use primitives correctly — returns code examples, API reference, and usage patterns inline.
npx shadcn@latest migrate rtl # RTL support migration
npx shadcn@latest migrate radix # Migrate to unified radix-ui package
npx shadcn@latest migrate icons # Icon library changes
# Migrate components outside the default ui directory
npx shadcn@latest migrate radix src/components/custom
shadcn/skills gives coding agents the context they need to work with components and registries correctly. It covers both Radix and Base UI primitives, updated APIs, component patterns, and registry workflows. The skill knows how to use the CLI, when to invoke it, and which flags to pass — so agents produce code that matches your design system.
Install: pnpm dlx skills add shadcn/ui
The new-york style now uses a single radix-ui package instead of individual @radix-ui/react-* packages:
// OLD — individual packages
import * as DialogPrimitive from "@radix-ui/react-dialog"
// NEW — unified package
import { Dialog as DialogPrimitive } from "radix-ui"
To migrate existing projects: npx shadcn@latest migrate radix. After migration, remove unused @radix-ui/react-* packages from package.json.
shadcn/ui now supports Base UI as an alternative to Radix UI for the underlying primitive library. Components look and behave the same way regardless of which library you choose — only the underlying implementation changes.
Choose during init: npx shadcn@latest init --base base-ui
The CLI pulls the correct component variant based on your project configuration automatically.
The components.json file configures how shadcn/ui works in your project:
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/app/globals.css",
"baseColor": "zinc", // Options: gray, neutral, slate, stone, zinc, mauve, olive, mist, taupe
"cssVariables": true
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"registries": {
"v0": {
"url": "https://v0.dev/chat/api/registry"
},
"ai-elements": {
"url": "https://elements.ai-sdk.dev/api/registry"
}
}
}
Configure multiple registries for your project:
{
"registries": {
"acme": {
"url": "https://acme.com/registry/{name}.json"
},
"private": {
"url": "https://internal.company.com/registry/{name}.json",
"headers": {
"Authorization": "Bearer ${REGISTRY_TOKEN}"
}
}
}
}
Install using namespace syntax:
npx shadcn@latest add @acme/header @private/auth-form
shadcn/ui uses CSS custom properties for theming, defined in globals.css:
@theme inline {
--color-background: oklch(0.145 0 0);
--color-foreground: oklch(0.985 0 0);
--color-card: oklch(0.205 0 0);
--color-card-foreground: oklch(0.985 0 0);
--color-primary: oklch(0.488 0.243 264.376);
--color-primary-foreground: oklch(0.985 0 0);
--color-secondary: oklch(0.269 0 0);
--color-secondary-foreground: oklch(0.985 0 0);
--color-muted: oklch(0.269 0 0);
--color-muted-foreground: oklch(0.708 0 0);
--color-accent: oklch(0.269 0 0);
--color-accent-foreground: oklch(0.985 0 0);
--color-destructive: oklch(0.396 0.141 25.723);
--color-border: oklch(0.269 0 0);
--color-input: oklch(0.269 0 0);
--color-ring: oklch(0.488 0.243 264.376);
--radius: 0.625rem;
/* CLI v4: radius tokens use multiplicative calc instead of additive */
--radius-xs: calc(var(--radius) * 0.5);
--radius-sm: calc(var(--radius) * 0.75);
--radius-md: calc(var(--radius) * 0.875);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) * 1.5);
}
For dark mode, use the dark class on <html>:
// app/layout.tsx
<html lang="en" className="dark">
Or use next-themes for toggling:
import { ThemeProvider } from 'next-themes'
<ThemeProvider attribute="class" defaultTheme="dark">
{children}
</ThemeProvider>
Add application-specific colors alongside shadcn defaults:
@theme inline {
/* shadcn defaults above... */
/* Custom app colors */
--color-priority-urgent: oklch(0.637 0.237 15.163);
--color-priority-high: oklch(0.705 0.213 47.604);
--color-status-done: oklch(0.723 0.219 149.579);
}
Use in components:
<span className="text-[var(--color-priority-urgent)]">Urgent</span>
// Or with Tailwind v4 theme():
<span className="text-priority-urgent">Urgent</span>
| Component | Use Case |
|---|---|
button | Actions, form submission |
card | Content containers |
dialog | Modals, confirmation prompts |
input / textarea | Form fields |
select | Dropdowns |
table |
shadcn/ui is not only a component source generator. In the Vercel stack it is the default interface language. Do not stop at "the component works." Compose pages that feel deliberate, high-signal, and consistent.
new-york for product, dashboard, AI, and admin surfaces.--color-primary.bg-background, bg-card, text-foreground, text-muted-foreground, border-border, ring-ring. Avoid ad-hoc hex values.--radius: 0.625rem is a strong baseline.| Use case | Reach for this first | Why |
|---|---|---|
| Settings page | Tabs + Card + Form | Clear information grouping with predictable save flows |
| Data dashboard | Card + Badge + Table + DropdownMenu | Covers summary, status, dense data, and row actions without custom shells |
| CRUD table | + + + |
Tabs + Card per group + Separator + save actionCards + filter bar + TableBadge + main Card + side Card + AlertDialog for destructiveCommand for quick find, Popover for pickers, for mobile filtersbutton / input / select / div when shadcn primitives existdiv rounded-xl border p-6 instead of Tabs / Table / Sheet / DialogDialog for destructive confirmation instead of Create your own component registry to share across projects:
| Type | Purpose |
|---|---|
registry:ui | Individual UI components |
registry:base | Full design system payload — components, deps, CSS vars, fonts, config |
registry:font | Font configuration as a first-class registry item |
[
{
"name": "my-component",
"type": "registry:ui",
"title": "My Component",
"description": "A custom component",
"files": [
{
"path": "components/my-component.tsx",
"type": "registry:ui"
}
],
"dependencies": ["lucide-react"]
}
]
npx shadcn@latest build
# Outputs to public/r/my-component.json
npx shadcn@latest add https://your-domain.com/r/my-component.json
shadcn init Breaks Geist Font in Next.js (Tailwind v4)shadcn init rewrites globals.css and may introduce --font-sans: var(--font-sans) — a circular self-reference that breaks font loading. Tailwind v4's @theme inline resolves CSS custom properties at parse time , not runtime — so even var(--font-geist-sans) won't work because Next.js injects that variable via className at runtime.
The fix : Use literal font family names in @theme inline:
/* In @theme inline — CORRECT (literal names) */
--font-sans: "Geist", "Geist Fallback", ui-sans-serif, system-ui, sans-serif;
--font-mono: "Geist Mono", "Geist Mono Fallback", ui-monospace, monospace;
/* WRONG — circular, resolves to nothing */
--font-sans: var(--font-sans);
/* ALSO WRONG — @theme inline can't resolve runtime CSS variables */
--font-sans: var(--font-geist-sans);
After runningshadcn init, always:
@theme inline with literal Geist font names (as shown above)<body> to <html> in layout.tsx:// layout.tsx — font variables on <html>, not <body>
<html lang="en" className={`${geistSans.variable} ${geistMono.variable}`}>
<body className="antialiased">
size PropThe shadcn Avatar component does not accept a size variant prop. Control size with Tailwind classes:
// WRONG — no size variant exists
<Avatar size="lg" /> // ❌ TypeScript error / silently ignored
// CORRECT — use Tailwind
<Avatar className="h-12 w-12">
<AvatarImage src={user.image} />
<AvatarFallback>JD</AvatarFallback>
</Avatar>
// Small avatar
<Avatar className="h-6 w-6"> ... </Avatar>
This applies to most shadcn components — they use Tailwind classes for sizing, not variant props. If you need reusable size variants, add them yourself via cva in the component source.
All shadcn components use the cn() utility for conditional class merging:
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Since you own the source code, extend components directly:
// components/ui/button.tsx — add your custom variant
const buttonVariants = cva('...', {
variants: {
variant: {
default: '...',
destructive: '...',
// Add custom variants
success: 'bg-green-600 text-white hover:bg-green-700',
premium: 'bg-gradient-to-r from-purple-500 to-pink-500 text-white',
},
},
})
Many components require TooltipProvider at the root:
// app/layout.tsx
import { TooltipProvider } from '@/components/ui/tooltip'
export default function RootLayout({ children }) {
return (
<html lang="en" className="dark">
<body>
<TooltipProvider>{children}</TooltipProvider>
</body>
</html>
)
}
Presets bundle your entire design system config (colors, theme, icon library, fonts, radius) into a single shareable code. One string configures everything:
# Apply a preset during init
npx shadcn@latest init --preset <code>
# Switch presets in an existing project (reconfigures everything including components)
npx shadcn@latest init --preset <code>
Build custom presets on shadcn/create — preview how colors, fonts, and radius apply to real components before publishing.
The CLI handles RTL transformation at install time:
npx shadcn@latest migrate rtl
Converts directional classes (ml-4, left-2) to logical properties (ms-4, start-2) automatically.
Weekly Installs
63
Repository
GitHub Stars
88
First Seen
Mar 7, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
opencode61
codex61
gemini-cli60
cursor60
github-copilot60
amp60
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
123,700 周安装
tanstack-start--preset — Apply a design system preset (colors, theme, icons, fonts, radius) as a single shareable code--base — Choose primitive library: radix (default) or base-ui--monorepo — Set up a monorepo structure| Data display |
tabs | View switching |
command | Command palette (Cmd+K) |
dropdown-menu | Context menus |
popover | Floating content |
tooltip | Hover hints |
badge | Status indicators |
avatar | User profile images |
scroll-area | Scrollable containers |
separator | Visual dividers |
label | Form labels |
sheet | Slide-out panels |
skeleton | Loading placeholders |
gap-6 / p-6 / text-sm) or compact (gap-4 / p-4 / text-sm).h-4 w-4 or h-5 w-5.TableDropdownMenuSheetAlertDialog| Supports browse, act, edit, and destructive confirmation in a standard pattern |
| Auth screen | Card + Label + Input + Button + Alert | Keeps entry flows focused and gives errors a proper treatment |
| Global search | Command + Dialog | Fast keyboard-first discovery with an established interaction model |
| Mobile nav | Sheet + Button + Separator | Provides a compact navigation shell that adapts cleanly to small screens |
| Detail page | header + Badge + Separator + Card | Balances hierarchy, metadata, and supporting content without over-nesting |
| Filters | Card sidebar + Sheet + Select | Works for persistent desktop filters and collapsible mobile controls |
| Empty/loading/error states | Card + Skeleton + Alert | Gives non-happy paths a designed surface instead of placeholder text |
SheetCard + social Separator + inline Alert for errorsAlertDialog (not Dialog) for confirmationAlertDialog