shadcn-best-practices

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

shadcn/ui Best Practices

shadcn/ui 最佳实践

This skill covers best practices for working with shadcn/ui — component imports, className utilities, form building, theming, and data tables.
本技能涵盖使用shadcn/ui的最佳实践——组件导入、className工具类、表单构建、主题设置和数据表格相关内容。

Use-When

适用场景

This skill activates when:
  • Agent works with shadcn/ui components
  • Agent adds or imports shadcn components
  • Agent builds forms with validation
  • Agent configures theming or dark mode
  • Agent creates data tables
当以下情况时激活本技能:
  • Agent 处理 shadcn/ui 组件
  • Agent 添加或导入 shadcn 组件
  • Agent 构建带验证的表单
  • Agent 配置主题或深色模式
  • Agent 创建数据表格

Core Rules

核心规则

  • ALWAYS import shadcn components from
    @/components/ui/{component-name}
  • ALWAYS use the
    cn()
    utility for className merging
  • ALWAYS use Zod + React Hook Form for form validation
  • ALWAYS use CSS variables for theming (not hardcoded colors)
  • ALWAYS use TanStack Table for data tables
  • ALWAYS check components.json to identify the primitive library (Radix vs Base UI)
  • ALWAYS use migration commands when upgrading between styles (
    migrate radix
    ,
    migrate rtl
    )
  • 始终从
    @/components/ui/{component-name}
    导入 shadcn 组件
  • 始终使用
    cn()
    工具类合并 className
  • 始终使用 Zod + React Hook Form 进行表单验证
  • 始终使用 CSS variables 进行主题设置(不要硬编码颜色)
  • 始终使用 TanStack Table 构建数据表格
  • 始终检查 components.json 以确定底层基础库(Radix vs Base UI)
  • 升级样式时始终使用迁移命令(
    migrate radix
    migrate rtl

Common Agent Mistakes

Agent 常见错误

  • Using relative paths instead of alias paths
  • Forgetting to import
    cn()
    utility
  • Hardcoding colors instead of using CSS variables
  • Building table logic manually instead of using TanStack Table
  • Assuming all shadcn projects use Radix UI (Base UI is now available)
  • Using Radix-specific imports in Base UI projects (or vice versa)
  • 使用相对路径而非别名路径
  • 忘记导入
    cn()
    工具类
  • 硬编码颜色而非使用 CSS variables
  • 手动构建表格逻辑而非使用 TanStack Table
  • 假设所有 shadcn 项目都使用 Radix UI(现在也支持 Base UI)
  • 在 Base UI 项目中使用 Radix 专属导入(反之亦然)

Examples

示例

✅ Correct

✅ 正确

tsx
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { cn } from "@/lib/utils"

function MyComponent({ className }) {
  return (
    <Button className={cn("base-class", className)}>
      <Input placeholder="Enter email" />
    </Button>
  )
}
tsx
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { cn } from "@/lib/utils"

function MyComponent({ className }) {
  return (
    <Button className={cn("base-class", className)}>
      <Input placeholder="Enter email" />
    </Button>
  )
}

❌ Wrong

❌ 错误

tsx
// Using relative paths
import { Button } from "../../components/ui/button"

// Hardcoding colors
<Button className="bg-blue-500 text-white" />

// Building table manually
data.map(item => <tr><td>{item.name}</td></tr>)

// Assuming Radix - wrong for Base UI projects
import * as DialogPrimitive from "@radix-ui/react-dialog"
tsx
// Using relative paths
import { Button } from "../../components/ui/button"

// Hardcoding colors
<Button className="bg-blue-500 text-white" />

// Building table manually
data.map(item => <tr><td>{item.name}</td></tr>)

// Assuming Radix - wrong for Base UI projects
import * as DialogPrimitive from "@radix-ui/react-dialog"

Identifying Primitive Library

识别基础库

tsx
// Check components.json to determine which library the project uses
// Look for "style" field:
// - "base-*" styles use @base-ui/react
// - Other styles use @radix-ui/react-* or radix-ui

// Example: reading the config
// import fs from "fs"
// const config = JSON.parse(fs.readFileSync("components.json", "utf-8"))
// config.style === "base-vega" // true = Base UI, false = Radix

// The API is identical regardless of library
import { Dialog, DialogContent } from "@/components/ui/dialog"
// Works the same for both Radix and Base UI projects
tsx
// Check components.json to determine which library the project uses
// Look for "style" field:
// - "base-*" styles use @base-ui/react
// - Other styles use @radix-ui/react-* or radix-ui

// Example: reading the config
// import fs from "fs"
// const config = JSON.parse(fs.readFileSync("components.json", "utf-8"))
// config.style === "base-vega" // true = Base UI, false = Radix

// The API is identical regardless of library
import { Dialog, DialogContent } from "@/components/ui/dialog"
// Works the same for both Radix and Base UI projects

References

参考资料