shadcn-component-review

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

shadcn Component Review

shadcn组件审查

Systematic review process for ensuring custom components and layouts align with shadcn design patterns, official theme styles, and Radix UI best practices.
用于确保自定义组件和布局符合shadcn设计模式、官方主题样式及Radix UI最佳实践的系统性审查流程。

Quick Start

快速开始

Planning Phase (Preventive)

规划阶段(预防性)

Before building a component:
  1. Check existing patterns: Review similar components in
    src/ui/
    and
    src/components/
  2. Reference your theme style: See references/theme-styles.md for spacing/shape patterns
  3. Use shadcn MCP (if available): Query components via shadcn MCP server
  4. Review checklist: Use references/review-checklist.md as planning guide
构建组件前:
  1. 检查现有模式:查看
    src/ui/
    src/components/
    中的同类组件
  2. 参考主题样式:查阅references/theme-styles.md获取间距/形状规范
  3. 使用shadcn MCP(若可用):通过shadcn MCP服务器查询组件
  4. 审查清单:使用references/review-checklist.md作为规划指南

Review Phase (Post-Build)

审查阶段(构建后)

After building a component:
  1. Run spacing audit: Check against your theme's spacing patterns
  2. Verify structure: Ensure proper use of
    data-slot
    attributes and composition
  3. Check design tokens: Verify semantic tokens only (no hardcoded colors)
  4. Test composability: Ensure component can be reused and customized via props
  5. Validate responsive: Test mobile-first approach and breakpoints
组件构建完成后:
  1. 执行间距审计:对照主题的间距规范检查
  2. 验证结构:确保
    data-slot
    属性和组件组合使用正确
  3. 检查设计令牌:仅使用语义化令牌(无硬编码颜色)
  4. 测试可组合性:确保组件可通过props复用和自定义
  5. 响应式验证:测试移动端优先的实现方案和断点适配

Core Review Areas

核心审查维度

1. Spacing (Theme-Dependent)

1. 间距(主题相关)

Use
gap-*
for flex/grid containers. Spacing varies by theme style:
ThemeSpacingShape
VegaStandardClassic shadcn
NovaCompactReduced padding/margins
MaiaGenerousSoft, rounded
LyraStandardBoxy, sharp
MiraDenseCompact interfaces
See references/theme-styles.md for theme-specific patterns.
flex/grid容器使用
gap-*
设置间距,不同主题的间距规范不同:
主题间距样式
Vega标准经典shadcn
Nova紧凑内边距/外边距缩减
Maia宽松柔和圆角
Lyra标准方正锐利
Mira密集紧凑型界面
查阅references/theme-styles.md获取各主题的具体规范。

2. Component Structure

2. 组件结构

  • Use
    data-slot
    attributes:
    data-slot="component-name"
  • Sub-components:
    ComponentName.Header
    ,
    ComponentName.Content
  • Composition over modification (never edit
    src/ui/*
    directly)
  • 使用
    data-slot
    属性:
    data-slot="component-name"
  • 子组件命名规范:
    组件名.Header
    组件名.Content
  • 优先组合而非修改(禁止直接编辑
    src/ui/*
    下的文件)

3. Design Tokens

3. 设计令牌

Semantic tokens only - never hardcoded colors:
tsx
// ✅ text-muted-foreground, bg-muted, hover:bg-accent
// ❌ text-neutral-500, bg-gray-100, hover:bg-neutral-50
仅使用语义化令牌,绝对禁止硬编码颜色:
tsx
// ✅ text-muted-foreground, bg-muted, hover:bg-accent
// ❌ text-neutral-500, bg-gray-100, hover:bg-neutral-50

4. Composability

4. 可组合性

  • Prop-based customization (variants, sizes)
  • Slot-based composition (children, content blocks)
  • Single responsibility, clear interface
  • 基于props的自定义能力(变体、尺寸)
  • 基于插槽的组合能力(children、内容块)
  • 单一职责,接口清晰

5. Responsive Design

5. 响应式设计

  • Mobile-first (< 768px base)
  • Breakpoints:
    md:
    (768px+),
    lg:
    (1024px+)
  • Touch targets: min 44px
  • Flex children:
    min-w-0
    to prevent overflow
See references/review-checklist.md for detailed checklists.
  • 移动端优先(<768px为基础尺寸)
  • 断点:
    md:
    (768px+)、
    lg:
    (1024px+)
  • 触摸目标:最小44px
  • Flex子元素:设置
    min-w-0
    防止溢出
查阅references/review-checklist.md获取详细审查清单。

Foundational Patterns

基础模式

CVA (Class Variance Authority)

CVA(Class Variance Authority)

shadcn components use CVA for type-safe, declarative variants:
tsx
import { cva, type VariantProps } from "class-variance-authority"

const buttonVariants = cva(
  "inline-flex items-center justify-center font-medium transition-colors",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        outline: "border border-input bg-background hover:bg-accent",
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 px-3 text-sm",
      },
    },
    defaultVariants: { variant: "default", size: "default" },
  }
)

interface ButtonProps extends VariantProps<typeof buttonVariants> {}
Key points:
  • Base styles in first argument (always applied)
  • Variants as declarative object
  • Type-safe props via
    VariantProps
  • Extend with new variants, don't modify base
shadcn组件使用CVA实现类型安全的声明式变体:
tsx
import { cva, type VariantProps } from "class-variance-authority"

const buttonVariants = cva(
  "inline-flex items-center justify-center font-medium transition-colors",
  {
    variants: {
      variant: {
        default: "bg-primary text-primary-foreground hover:bg-primary/90",
        outline: "border border-input bg-background hover:bg-accent",
      },
      size: {
        default: "h-9 px-4 py-2",
        sm: "h-8 px-3 text-sm",
      },
    },
    defaultVariants: { variant: "default", size: "default" },
  }
)

interface ButtonProps extends VariantProps<typeof buttonVariants> {}
核心要点:
  • 基础样式放在第一个参数(始终生效)
  • 变体以声明式对象定义
  • 通过
    VariantProps
    实现类型安全的props
  • 扩展新变体,不要修改基础配置

cn() Utility

cn()工具函数

Always use
cn()
for conditional and override classes:
tsx
import { cn } from "@/lib/utils"

// Combines clsx (conditionals) + tailwind-merge (conflict resolution)
<div className={cn(
  "base-classes",
  isActive && "active-classes",
  className // allows consumer overrides
)} />
Why it matters:
  • Prevents CSS cascade conflicts
  • Enables prop-based class overrides
  • Handles conditional classes cleanly
始终使用
cn()
处理条件类和样式覆盖:
tsx
import { cn } from "@/lib/utils"

// 结合了clsx(条件处理)+ tailwind-merge(冲突解决)的能力
<div className={cn(
  "base-classes",
  isActive && "active-classes",
  className // 允许使用方覆盖样式
)} />
价值:
  • 避免CSS层叠冲突
  • 支持基于props的类名覆盖
  • 简洁处理条件类

Theme-Aware Styling

主题感知样式

shadcn themes use CSS variables for consistent styling across components.
Border radius is theme-defined via
--radius
:
tsx
// ✅ Uses theme radius (adapts to Maia rounded vs Lyra sharp)
<Button className="rounded-md">  // Uses --radius variable
<Card className="rounded-lg">

// ❌ Hardcoded (ignores theme settings)
<Button className="rounded-[20px]">
Theme CSS variables (defined in your theme's CSS):
  • --radius
    - Base radius unit
  • --background
    ,
    --foreground
    - Base colors
  • --primary
    ,
    --secondary
    ,
    --accent
    - Semantic colors
  • --muted
    ,
    --card
    ,
    --popover
    - Surface colors
Custom theme extensions: If your project needs theme-switchable radius (e.g., pill vs sharp), create utility classes mapped to CSS variables:
css
/* Example: Theme-switchable radius */
.rounded-theme-button {
  border-radius: var(--radius-button);
}
shadcn主题使用CSS变量实现组件间的样式一致性。
圆角通过
--radius
由主题定义:
tsx
// ✅ 使用主题圆角(适配Maia的圆角和Lyra的方角)
<Button className="rounded-md">  // 使用--radius变量
<Card className="rounded-lg">

// ❌ 硬编码(忽略主题设置)
<Button className="rounded-[20px]">
主题CSS变量(在主题CSS文件中定义):
  • --radius
    - 基础圆角单位
  • --background
    --foreground
    - 基础颜色
  • --primary
    --secondary
    --accent
    - 语义化颜色
  • --muted
    --card
    --popover
    - 表面颜色
自定义主题扩展:如果项目需要支持可切换的圆角(比如胶囊形 vs 锐利),可以创建映射到CSS变量的工具类:
css
/* 示例:可切换的主题圆角 */
.rounded-theme-button {
  border-radius: var(--radius-button);
}

Animation Patterns

动效模式

Use consistent, subtle animations. See references/animation-patterns.md for:
  • Timing standards (150ms fast, 200ms normal, 300ms slow)
  • Easing curves (ease-out for enter, ease-in for exit)
  • Radix
    data-state
    animation patterns
  • Framer Motion patterns for enter/exit
  • Accessibility (
    motion-safe:
    prefixes)
使用统一的轻量动效,查阅references/animation-patterns.md获取:
  • 时长标准(150ms快、200ms正常、300ms慢)
  • 缓动曲线(入场用ease-out、离场用ease-in)
  • Radix
    data-state
    动效模式
  • Framer Motion入场/离场模式
  • 可访问性(
    motion-safe:
    前缀)

Resources

资源

shadcn Documentation

shadcn文档

2025 Updates

2025更新

Visual Styles (via
npx shadcn create
):
  • Vega - Classic shadcn/ui look
  • Nova - Compact layouts, reduced spacing
  • Maia - Soft and rounded, generous spacing
  • Lyra - Boxy and sharp, pairs with mono fonts
  • Mira - Dense interfaces
New utility components:
  • input-group
    /
    button-group
    - Grouped controls
  • empty
    - Empty state patterns
  • field
    - Form field wrapper
  • spinner
    - Loading indicator
Technical updates:
  • Full Tailwind v4 support (
    @theme
    directive)
  • OKLCH colors (from HSL)
  • React 19 compatibility
视觉样式(通过
npx shadcn create
使用):
  • Vega - 经典shadcn/ui外观
  • Nova - 紧凑布局,缩减间距
  • Maia - 柔和圆角,宽松间距
  • Lyra - 方正锐利,搭配等宽字体使用
  • Mira - 密集界面
新增工具组件
  • input-group
    /
    button-group
    - 分组控件
  • empty
    - 空状态模式
  • field
    - 表单字段包装器
  • spinner
    - 加载指示器
技术更新
  • 完全支持Tailwind v4(
    @theme
    指令)
  • 颜色体系从HSL切换为OKLCH
  • 兼容React 19

Community Tools

社区工具

Review Workflow

审查工作流

Step 1: Structure Review

步骤1:结构审查

Check component structure against shadcn patterns:
tsx
// ✅ Good: Proper structure with data-slot
<div data-slot="component-name" className="flex flex-col gap-4">
  <div data-slot="component-header" className="flex flex-col gap-2">
    {/* Header content */}
  </div>
  <div data-slot="component-content">
    {/* Main content */}
  </div>
</div>

// ❌ Bad: Missing data-slot, inconsistent spacing
<div className="space-y-4">
  <div className="mb-2">
    {/* Header content */}
  </div>
  <div>
    {/* Main content */}
  </div>
</div>
对照shadcn模式检查组件结构:
tsx
// ✅ 优秀:结构规范,包含data-slot
<div data-slot="component-name" className="flex flex-col gap-4">
  <div data-slot="component-header" className="flex flex-col gap-2">
    {/* 头部内容 */}
  </div>
  <div data-slot="component-content">
    {/* 主内容 */}
  </div>
</div>

// ❌ 不佳:缺少data-slot,间距不统一
<div className="space-y-4">
  <div className="mb-2">
    {/* 头部内容 */}
  </div>
  <div>
    {/* 主内容 */}
  </div>
</div>

Step 2: Spacing Audit

步骤2:间距审计

Verify spacing follows your theme's patterns:
  • Check all flex containers use
    gap-*
    not
    space-y-*
    or margins
  • Verify spacing values follow Tailwind scale (2, 4, 6, 8, etc.)
  • Ensure responsive spacing uses
    gap-X md:gap-Y
    pattern
  • Match spacing density to your theme (Maia=generous, Nova/Mira=compact)
验证间距符合主题规范:
  • 检查所有flex容器使用
    gap-*
    而非
    space-y-*
    或margin
  • 验证间距值遵循Tailwind刻度(2、4、6、8等)
  • 确保响应式间距使用
    gap-X md:gap-Y
    模式
  • 间距密度匹配主题(Maia=宽松、Nova/Mira=紧凑)

Step 3: Design Token Check

步骤3:设计令牌检查

Verify semantic tokens only:
bash
undefined
验证仅使用语义化令牌:
bash
undefined

Check for hardcoded colors

检查硬编码颜色

grep -r "neutral-|gray-|slate-" [component-file]
undefined
grep -r "neutral-|gray-|slate-" [component-file]
undefined

Step 4: Composability Review

步骤4:可组合性审查

Ensure component can be:
  • Reused in other contexts
  • Customized via props (variants, sizes)
  • Composed with other components
  • Extended without modification
确保组件满足以下要求:
  • 可在其他场景复用
  • 可通过props自定义(变体、尺寸)
  • 可与其他组件组合
  • 无需修改即可扩展

Step 5: Responsive Verification

步骤5:响应式验证

Test at breakpoints:
  • Mobile: 375px
  • Tablet: 768px
  • Desktop: 1280px
在不同断点下测试:
  • 移动端:375px
  • 平板:768px
  • 桌面端:1280px

Examples

示例

Good Component Pattern

优秀组件模式

tsx
// ✅ Follows shadcn patterns
export function PageContent({
  heading,
  description,
  contentBlock,
  children,
}: PageContentProps) {
  return (
    <div
      data-slot="page-content"
      className="min-w-0 flex flex-col gap-4 md:gap-6"
    >
      <div data-slot="page-content-header" className="flex flex-col gap-2">
        <h1 className="text-xl md:text-2xl tracking-tight font-semibold text-foreground">
          {heading}
        </h1>
        {description && (
          <p className="text-sm text-muted-foreground">{description}</p>
        )}
      </div>
      {contentBlock && (
        <div data-slot="page-content-block">{contentBlock}</div>
      )}
      {children}
    </div>
  );
}
tsx
// ✅ 符合shadcn模式
export function PageContent({
  heading,
  description,
  contentBlock,
  children,
}: PageContentProps) {
  return (
    <div
      data-slot="page-content"
      className="min-w-0 flex flex-col gap-4 md:gap-6"
    >
      <div data-slot="page-content-header" className="flex flex-col gap-2">
        <h1 className="text-xl md:text-2xl tracking-tight font-semibold text-foreground">
          {heading}
        </h1>
        {description && (
          <p className="text-sm text-muted-foreground">{description}</p>
        )}
      </div>
      {contentBlock && (
        <div data-slot="page-content-block">{contentBlock}</div>
      )}
      {children}
    </div>
  );
}

Bad Component Pattern

不佳组件模式

tsx
// ❌ Violates multiple patterns
export function PageContent({ heading, description }: Props) {
  return (
    <div className="space-y-6">
      <div className="mb-4">
        <h1 className="text-2xl font-bold text-gray-900">{heading}</h1>
        <p className="mt-2 text-sm text-neutral-500">{description}</p>
      </div>
    </div>
  );
}
Issues:
  • Uses
    space-y-*
    instead of
    gap-*
  • Hardcoded colors (
    text-gray-900
    ,
    text-neutral-500
    )
  • Missing
    data-slot
    attributes
  • Inconsistent spacing (
    mb-4
    ,
    mt-2
    instead of flex gap)
tsx
// ❌ 违反多项规范
export function PageContent({ heading, description }: Props) {
  return (
    <div className="space-y-6">
      <div className="mb-4">
        <h1 className="text-2xl font-bold text-gray-900">{heading}</h1>
        <p className="mt-2 text-sm text-neutral-500">{description}</p>
      </div>
    </div>
  );
}
问题:
  • 使用
    space-y-*
    而非
    gap-*
  • 硬编码颜色(
    text-gray-900
    text-neutral-500
  • 缺少
    data-slot
    属性
  • 间距不统一(使用
    mb-4
    mt-2
    而非flex gap)

Additional Resources

其他资源

  • Theme Styles: references/theme-styles.md
  • Review Checklist: references/review-checklist.md
  • Animation Patterns: references/animation-patterns.md
  • V2 Enhancement Ideas: references/v2-notes.md
  • 主题样式references/theme-styles.md
  • 审查清单references/review-checklist.md
  • 动效模式references/animation-patterns.md
  • V2优化思路references/v2-notes.md