shadcn-component-review
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseshadcn 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:
- Check existing patterns: Review similar components in and
src/ui/src/components/ - Reference your theme style: See references/theme-styles.md for spacing/shape patterns
- Use shadcn MCP (if available): Query components via shadcn MCP server
- Review checklist: Use references/review-checklist.md as planning guide
构建组件前:
- 检查现有模式:查看和
src/ui/中的同类组件src/components/ - 参考主题样式:查阅references/theme-styles.md获取间距/形状规范
- 使用shadcn MCP(若可用):通过shadcn MCP服务器查询组件
- 审查清单:使用references/review-checklist.md作为规划指南
Review Phase (Post-Build)
审查阶段(构建后)
After building a component:
- Run spacing audit: Check against your theme's spacing patterns
- Verify structure: Ensure proper use of attributes and composition
data-slot - Check design tokens: Verify semantic tokens only (no hardcoded colors)
- Test composability: Ensure component can be reused and customized via props
- Validate responsive: Test mobile-first approach and breakpoints
组件构建完成后:
- 执行间距审计:对照主题的间距规范检查
- 验证结构:确保属性和组件组合使用正确
data-slot - 检查设计令牌:仅使用语义化令牌(无硬编码颜色)
- 测试可组合性:确保组件可通过props复用和自定义
- 响应式验证:测试移动端优先的实现方案和断点适配
Core Review Areas
核心审查维度
1. Spacing (Theme-Dependent)
1. 间距(主题相关)
Use for flex/grid containers. Spacing varies by theme style:
gap-*| Theme | Spacing | Shape |
|---|---|---|
| Vega | Standard | Classic shadcn |
| Nova | Compact | Reduced padding/margins |
| Maia | Generous | Soft, rounded |
| Lyra | Standard | Boxy, sharp |
| Mira | Dense | Compact 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 attributes:
data-slotdata-slot="component-name" - Sub-components: ,
ComponentName.HeaderComponentName.Content - Composition over modification (never edit directly)
src/ui/*
- 使用属性:
data-slotdata-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-504. 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: (768px+),
md:(1024px+)lg: - Touch targets: min 44px
- Flex children: to prevent overflow
min-w-0
See references/review-checklist.md for detailed checklists.
- 移动端优先(<768px为基础尺寸)
- 断点:(768px+)、
md:(1024px+)lg: - 触摸目标:最小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> {}核心要点:
- 基础样式放在第一个参数(始终生效)
- 变体以声明式对象定义
- 通过实现类型安全的props
VariantProps - 扩展新变体,不要修改基础配置
cn() Utility
cn()工具函数
Always use for conditional and override classes:
cn()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 :
--radiustsx
// ✅ 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):
- - Base radius unit
--radius - ,
--background- Base colors--foreground - ,
--primary,--secondary- Semantic colors--accent - ,
--muted,--card- Surface colors--popover
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变量实现组件间的样式一致性。
圆角通过由主题定义:
--radiustsx
// ✅ 使用主题圆角(适配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 animation patterns
data-state - Framer Motion patterns for enter/exit
- Accessibility (prefixes)
motion-safe:
使用统一的轻量动效,查阅references/animation-patterns.md获取:
- 时长标准(150ms快、200ms正常、300ms慢)
- 缓动曲线(入场用ease-out、离场用ease-in)
- Radix 动效模式
data-state - Framer Motion入场/离场模式
- 可访问性(前缀)
motion-safe:
Resources
资源
shadcn Documentation
shadcn文档
- Components: https://ui.shadcn.com/docs/components
- Blocks: https://ui.shadcn.com/blocks
- Themes: https://ui.shadcn.com/themes
- Theme Creator: https://ui.shadcn.com/create
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- Grouped controlsbutton-group - - Empty state patterns
empty - - Form field wrapper
field - - Loading indicator
spinner
Technical updates:
- Full Tailwind v4 support (directive)
@theme - 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
社区工具
- tweakcn: https://tweakcn.com/ - Interactive theme editor
- Shadcn Studio: https://shadcnstudio.com/ - Theme generator
- Shadcn Themer: https://shadcnthemer.com/ - Theme creator
- tweakcn:https://tweakcn.com/ - 交互式主题编辑器
- Shadcn Studio:https://shadcnstudio.com/ - 主题生成器
- Shadcn Themer:https://shadcnthemer.com/ - 主题创建器
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 not
gap-*or marginsspace-y-* - Verify spacing values follow Tailwind scale (2, 4, 6, 8, etc.)
- Ensure responsive spacing uses pattern
gap-X md:gap-Y - Match spacing density to your theme (Maia=generous, Nova/Mira=compact)
验证间距符合主题规范:
- 检查所有flex容器使用而非
gap-*或marginspace-y-* - 验证间距值遵循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
undefinedCheck for hardcoded colors
检查硬编码颜色
grep -r "neutral-|gray-|slate-" [component-file]
undefinedgrep -r "neutral-|gray-|slate-" [component-file]
undefinedStep 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 instead of
space-y-*gap-* - Hardcoded colors (,
text-gray-900)text-neutral-500 - Missing attributes
data-slot - Inconsistent spacing (,
mb-4instead of flex gap)mt-2
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而非flex gap)mt-2
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