ui-design-system
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseUI Design System
UI设计系统
When to Use
适用场景
Activate this skill when:
- Creating new UI components that must follow a design system
- Building page layouts with consistent spacing and structure
- Setting up or extending design tokens (colors, typography, spacing)
- Choosing colors, fonts, or spacing values for a project
- Reviewing UI code for design consistency and accessibility
- Integrating shadcn/ui components into existing layouts
Do NOT use this skill for:
- Backend API implementation (use )
python-backend-expert - Component or hook testing (use )
react-testing-patterns - E2E browser testing (use )
e2e-testing - General React patterns unrelated to design system (use )
react-frontend-expert - Deployment or CI/CD (use )
deployment-pipeline
在以下场景中使用该技能:
- 创建必须遵循设计系统的新UI组件
- 构建具有统一间距和结构的页面布局
- 设置或扩展设计令牌(颜色、排版、间距)
- 为项目选择颜色、字体或间距值
- 审查UI代码的设计一致性和无障碍性
- 将shadcn/ui组件集成到现有布局中
请勿在以下场景中使用该技能:
- 后端API实现(请使用)
python-backend-expert - 组件或Hook测试(请使用)
react-testing-patterns - 端到端浏览器测试(请使用)
e2e-testing - 与设计系统无关的通用React模式(请使用)
react-frontend-expert - 部署或CI/CD流程(请使用)
deployment-pipeline
Instructions
操作指南
Step 0: Read Existing Design Tokens
步骤0:读取现有设计令牌
Before generating any UI code, check the project for existing tokens:
- Read (or
tailwind.config.ts) for custom theme extensions.js - Read or
src/styles/globals.cssfor CSS custom propertiesapp/globals.css - Read if shadcn/ui is configured
components.json
If no design tokens exist, generate a starter set and ask the user to confirm before proceeding (see Edge Cases).
在生成任何UI代码之前,请检查项目中的现有令牌:
- 读取(或
tailwind.config.ts)中的自定义主题扩展.js - 读取或
src/styles/globals.css中的CSS自定义属性app/globals.css - 如果已配置shadcn/ui,请读取
components.json
如果没有现有设计令牌,请生成一套初始令牌,并在继续之前请求用户确认(请参阅边缘情况部分)。
Design Tokens
设计令牌
Color Tokens
颜色令牌
Define colors as CSS custom properties consumed by Tailwind. Never use hardcoded hex/rgb values in components.
CSS custom properties (HSL format for shadcn/ui compatibility):
css
/* globals.css */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222 47% 11%;
--primary: 221 83% 53%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--secondary-foreground: 222 47% 11%;
--muted: 210 40% 96%;
--muted-foreground: 215 16% 47%;
--accent: 210 40% 96%;
--accent-foreground: 222 47% 11%;
--destructive: 0 84% 60%;
--destructive-foreground: 210 40% 98%;
--border: 214 32% 91%;
--input: 214 32% 91%;
--ring: 221 83% 53%;
--radius: 0.5rem;
}
.dark {
--background: 222 47% 11%;
--foreground: 210 40% 98%;
--primary: 217 91% 60%;
--primary-foreground: 222 47% 11%;
--secondary: 217 33% 17%;
--secondary-foreground: 210 40% 98%;
--muted: 217 33% 17%;
--muted-foreground: 215 20% 65%;
--accent: 217 33% 17%;
--accent-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--border: 217 33% 17%;
--input: 217 33% 17%;
--ring: 224 76% 48%;
}
}Tailwind config mapping:
ts
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
},
},
},
} satisfies Config;Color usage rules:
- Always use semantic token classes: ,
bg-primary,text-foregroundborder-border - Never use raw Tailwind palette colors () in component code
bg-blue-500 - Every color must have a dark mode variant defined
- Use variants for text on colored backgrounds
foreground
将颜色定义为供Tailwind使用的CSS自定义属性。切勿在组件中使用硬编码的十六进制/RGB值。
CSS自定义属性(为兼容shadcn/ui采用HSL格式):
css
/* globals.css */
@layer base {
:root {
--background: 0 0% 100%;
--foreground: 222 47% 11%;
--primary: 221 83% 53%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96%;
--secondary-foreground: 222 47% 11%;
--muted: 210 40% 96%;
--muted-foreground: 215 16% 47%;
--accent: 210 40% 96%;
--accent-foreground: 222 47% 11%;
--destructive: 0 84% 60%;
--destructive-foreground: 210 40% 98%;
--border: 214 32% 91%;
--input: 214 32% 91%;
--ring: 221 83% 53%;
--radius: 0.5rem;
}
.dark {
--background: 222 47% 11%;
--foreground: 210 40% 98%;
--primary: 217 91% 60%;
--primary-foreground: 222 47% 11%;
--secondary: 217 33% 17%;
--secondary-foreground: 210 40% 98%;
--muted: 217 33% 17%;
--muted-foreground: 215 20% 65%;
--accent: 217 33% 17%;
--accent-foreground: 210 40% 98%;
--destructive: 0 63% 31%;
--destructive-foreground: 210 40% 98%;
--border: 217 33% 17%;
--input: 217 33% 17%;
--ring: 224 76% 48%;
}
}Tailwind配置映射:
ts
// tailwind.config.ts
export default {
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
},
},
},
} satisfies Config;颜色使用规则:
- 始终使用语义化令牌类:、
bg-primary、text-foregroundborder-border - 切勿在组件代码中使用原始Tailwind调色板颜色(如)
bg-blue-500 - 每种颜色都必须定义深色模式变体
- 在彩色背景上的文本请使用变体
foreground
Typography Scale
排版比例
Define a typographic scale using Tailwind's font-size utilities:
| Token | Size | Line Height | Usage |
|---|---|---|---|
| 12px | 16px | Captions, helper text |
| 14px | 20px | Secondary text, labels |
| 16px | 24px | Body text (default) |
| 18px | 28px | Subheadings |
| 20px | 28px | Section headings |
| 24px | 32px | Page headings |
| 30px | 36px | Hero headings |
Typography rules:
- Set a base font in :
tailwind.config.tsfontFamily: { sans: ["Inter", "system-ui", "sans-serif"] } - Use (500) for headings and labels,
font-medium(400) for bodyfont-normal - Use for headings
tracking-tightand abovetext-2xl - Limit line length with (65ch) for readability
max-w-prose
使用Tailwind的字体大小工具定义排版比例:
| 令牌 | 尺寸 | 行高 | 用途 |
|---|---|---|---|
| 12px | 16px | 说明文字、辅助文本 |
| 14px | 20px | 次要文本、标签 |
| 16px | 24px | 正文文本(默认) |
| 18px | 28px | 子标题 |
| 20px | 28px | 章节标题 |
| 24px | 32px | 页面标题 |
| 30px | 36px | 英雄区标题 |
排版规则:
- 在中设置基础字体:
tailwind.config.tsfontFamily: { sans: ["Inter", "system-ui", "sans-serif"] } - 标题和标签使用(500字重),正文使用
font-medium(400字重)font-normal - 及以上的标题使用
text-2xl字间距tracking-tight - 使用(65字符)限制行宽以提升可读性
max-w-prose
Spacing (8pt Grid)
间距(8pt网格)
All spacing values follow an 8pt base grid:
| Tailwind Class | Value | Use Case |
|---|---|---|
| 4px | Inline icon padding, tight gaps |
| 8px | Compact element spacing |
| 12px | Input padding, small card padding |
| 16px | Standard component padding |
| 24px | Card padding, section gaps |
| 32px | Section padding |
| 48px | Page section spacing |
| 64px | Major layout spacing |
Spacing rules:
- Use for flex/grid children instead of individual margins
gap-* - Prefer for vertical stacking of sibling elements
space-y-* - Cards: padding with
p-6between internal elementsgap-4 - Page sections: or
py-12vertical paddingpy-16 - Never mix spacing systems (no )
margin: 13px
所有间距值遵循8pt基础网格:
| Tailwind类 | 数值 | 使用场景 |
|---|---|---|
| 4px | 内联图标内边距、紧凑间距 |
| 8px | 紧凑元素间距 |
| 12px | 输入框内边距、小卡片内边距 |
| 16px | 标准组件内边距 |
| 24px | 卡片内边距、章节间距 |
| 32px | 章节内边距 |
| 48px | 页面章节间距 |
| 64px | 主要布局间距 |
间距规则:
- 对于flex/grid子元素,使用而非单独的外边距
gap-* - 垂直堆叠兄弟元素时优先使用
space-y-* - 卡片:使用内边距,内部元素间距为
p-6gap-4 - 页面章节:使用或
py-12垂直内边距py-16 - 切勿混合使用不同间距系统(如不要写)
margin: 13px
Component Structure
组件结构
Hierarchy: Container > Layout > Content
层级:容器 > 布局 > 内容
Every component follows a three-layer structure:
tsx
// Container: outer wrapper with spacing, background, border
<Card className="p-6">
{/* Layout: flex/grid arrangement */}
<div className="flex items-center gap-4">
{/* Content: actual UI elements */}
<Avatar src={user.avatar} alt={user.name} />
<div className="space-y-1">
<h3 className="text-sm font-medium">{user.name}</h3>
<p className="text-sm text-muted-foreground">{user.role}</p>
</div>
</div>
</Card>每个组件都遵循三层结构:
tsx
// 容器:包含间距、背景、边框的外层包装
<Card className="p-6">
{/* 布局:flex/grid排列方式 */}
<div className="flex items-center gap-4">
{/* 内容:实际UI元素 */}
<Avatar src={user.avatar} alt={user.name} />
<div className="space-y-1">
<h3 className="text-sm font-medium">{user.name}</h3>
<p className="text-sm text-muted-foreground">{user.role}</p>
</div>
</div>
</Card>Semantic HTML
语义化HTML
Use the correct HTML element for every purpose:
| Element | Use For | Not |
|---|---|---|
| Clickable actions | |
| Navigation links | |
| Navigation regions | |
| Primary page content | |
| Self-contained content (card, post) | |
| Thematic grouping with heading | |
| Sidebar or tangential content | |
| Introductory content for a section | |
| Footer content for a section | |
| Lists of items | |
为每个用途使用正确的HTML元素:
| 元素 | 适用场景 | 不适用场景 |
|---|---|---|
| 可点击操作 | |
| 导航链接 | 使用 |
| 导航区域 | |
| 页面主要内容 | |
| 独立内容块(卡片、文章) | |
| 带标题的主题分组 | |
| 侧边栏或次要内容 | |
| 章节的介绍性内容 | |
| 章节的页脚内容 | |
| 项目列表 | 每个项目都用 |
shadcn/ui Primitives
shadcn/ui基础组件
Prefer shadcn/ui components over custom implementations:
| Need | Use | Not |
|---|---|---|
| Buttons | | Custom |
| Modals | | Custom modal with portal |
| Dropdowns | | Custom dropdown |
| Cards | | Styled |
| Inputs | | Styled |
| Selects | | Native |
| Tooltips | | Custom tooltip |
| Tabs | | Custom tab component |
| Tables | | Plain |
| Alerts | | Custom banner div |
If shadcn/ui is not installed, fall back to plain Tailwind with equivalent patterns and consistent class ordering.
优先使用shadcn/ui组件而非自定义实现:
| 需求 | 推荐使用 | 不推荐使用 |
|---|---|---|
| 按钮 | | 带样式的自定义 |
| 模态框 | | 带portal的自定义模态框 |
| 下拉菜单 | | 自定义下拉菜单 |
| 卡片 | | 带样式的 |
| 输入框 | | 带样式的 |
| 选择器 | | 原生 |
| 工具提示 | | 自定义工具提示 |
| 标签页 | | 自定义标签页组件 |
| 表格 | | 普通 |
| 提示框 | | 自定义横幅 |
如果未安装shadcn/ui,请退而使用纯Tailwind实现等效模式,并保持类名顺序一致。
TypeScript Component Interfaces
TypeScript组件接口
Export props as TypeScript interfaces with JSDoc descriptions:
tsx
/** Props for the UserProfileCard component. */
interface UserProfileCardProps {
/** User data to display. */
user: User;
/** Called when the edit button is clicked. */
onEdit?: (userId: string) => void;
/** Visual variant of the card. */
variant?: "default" | "compact";
/** Additional CSS classes applied to the root element. */
className?: string;
}
export function UserProfileCard({
user,
onEdit,
variant = "default",
className,
}: UserProfileCardProps) {
// ...
}Props rules:
- Name interface
{ComponentName}Props - Include on every component for composition
className?: string - Use prop for visual variations, not separate components
variant - Default optional props in destructuring, not in interface
- Use union types for constrained string values:
"sm" | "md" | "lg"
将组件属性导出为带JSDoc注释的TypeScript接口:
tsx
/** UserProfileCard组件的属性 */
interface UserProfileCardProps {
/** 要显示的用户数据 */
user: User;
/** 点击编辑按钮时触发的回调 */
onEdit?: (userId: string) => void;
/** 卡片的视觉变体 */
variant?: "default" | "compact";
/** 应用于根元素的额外CSS类 */
className?: string;
}
export function UserProfileCard({
user,
onEdit,
variant = "default",
className,
}: UserProfileCardProps) {
// ...
}属性规则:
- 接口命名为
{组件名称}Props - 每个组件都要包含以支持组合
className?: string - 使用属性实现视觉变体,而非创建单独组件
variant - 在解构时为可选属性设置默认值,而非在接口中设置
- 对受限字符串值使用联合类型:
"sm" | "md" | "lg"
Responsive Design
响应式设计
Breakpoints
断点
Use Tailwind's mobile-first breakpoints:
| Prefix | Min Width | Target |
|---|---|---|
| (none) | 0px | Mobile (default) |
| 640px | Large phones / small tablets |
| 768px | Tablets |
| 1024px | Desktops |
| 1280px | Large desktops |
Responsive rules:
- Design mobile-first: base styles for mobile, then add breakpoint overrides
- Use for responsive grids
grid-cols-1 md:grid-cols-2 lg:grid-cols-3 - Stack navigation vertically on mobile:
flex-col md:flex-row - Hide non-essential elements on mobile:
hidden md:block - Set max container width:
max-w-7xl mx-auto px-4 sm:px-6 lg:px-8
使用Tailwind的移动端优先断点:
| 前缀 | 最小宽度 | 目标设备 |
|---|---|---|
| 无 | 0px | 移动端(默认) |
| 640px | 大屏手机/小平板 |
| 768px | 平板 |
| 1024px | 桌面端 |
| 1280px | 大屏桌面端 |
响应式规则:
- 采用移动端优先设计:基础样式适配移动端,然后添加断点覆盖样式
- 使用实现响应式网格
grid-cols-1 md:grid-cols-2 lg:grid-cols-3 - 移动端导航垂直堆叠:
flex-col md:flex-row - 移动端隐藏非必要元素:
hidden md:block - 设置容器最大宽度:
max-w-7xl mx-auto px-4 sm:px-6 lg:px-8
Responsive Layout Pattern
响应式布局示例
tsx
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{items.map((item) => (
<ItemCard key={item.id} item={item} />
))}
</div>
</div>tsx
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{items.map((item) => (
<ItemCard key={item.id} item={item} />
))}
</div>
</div>Accessibility (WCAG 2.1 AA)
无障碍性(WCAG 2.1 AA)
Contrast Ratios
对比度
- Normal text (< 18px or < 14px bold): minimum 4.5:1 contrast ratio
- Large text (>= 18px or >= 14px bold): minimum 3:1 contrast ratio
- UI components and graphical objects: minimum 3:1 contrast ratio
- 普通文本(<18px 或 <14px加粗):最小对比度4.5:1
- 大文本(≥18px 或 ≥14px加粗):最小对比度3:1
- UI组件和图形对象:最小对比度3:1
Interactive Element Requirements
交互元素要求
Every interactive element must have:
- Visible label or aria-label:
<Button aria-label="Close dialog">X</Button> - Focus indicator: Tailwind's utilities:
ringfocus-visible:ring-2 focus-visible:ring-ring - Keyboard access: Reachable via Tab, activatable via Enter/Space
- Disabled state: Both visual and or
aria-disabledattributedisabled
每个交互元素必须具备:
- 可见标签或aria-label:
<Button aria-label="关闭对话框">X</Button> - 焦点指示器:使用Tailwind的工具类:
ringfocus-visible:ring-2 focus-visible:ring-ring - 键盘可访问性:可通过Tab键聚焦,通过Enter/Space键激活
- 禁用状态:同时具备视觉样式和或
aria-disabled属性disabled
ARIA Patterns
ARIA模式
- Icon-only buttons:
aria-label="Delete item" - Loading states: on the loading container
aria-busy="true" - Dynamic content updates: on the container
aria-live="polite" - Form errors: on the input,
aria-invalid="true"on the messagerole="alert" - Modals: , focus trap, Escape to close
aria-modal="true" - Navigation landmarks:
<nav aria-label="Main navigation">
- 仅图标按钮:
aria-label="删除项目" - 加载状态:在加载容器上添加
aria-busy="true" - 动态内容更新:在容器上添加
aria-live="polite" - 表单错误:在输入框上添加,在错误消息上添加
aria-invalid="true"role="alert" - 模态框:、焦点捕获、按Esc键关闭
aria-modal="true" - 导航地标:
<nav aria-label="主导航">
Examples
示例
User Profile Card
用户资料卡片
tsx
interface UserProfileCardProps {
user: { id: string; name: string; role: string; avatarUrl: string };
onEdit?: (userId: string) => void;
className?: string;
}
export function UserProfileCard({ user, onEdit, className }: UserProfileCardProps) {
return (
<Card className={cn("p-6", className)}>
<div className="flex items-center gap-4">
<Avatar className="h-12 w-12">
<AvatarImage src={user.avatarUrl} alt={user.name} />
<AvatarFallback>{user.name.charAt(0)}</AvatarFallback>
</Avatar>
<div className="space-y-1">
<h3 className="text-sm font-medium leading-none">{user.name}</h3>
<p className="text-sm text-muted-foreground">{user.role}</p>
</div>
</div>
{onEdit && (
<div className="mt-4">
<Button
variant="outline"
size="sm"
onClick={() => onEdit(user.id)}
aria-label={`Edit ${user.name}'s profile`}
>
Edit Profile
</Button>
</div>
)}
</Card>
);
}tsx
interface UserProfileCardProps {
user: { id: string; name: string; role: string; avatarUrl: string };
onEdit?: (userId: string) => void;
className?: string;
}
export function UserProfileCard({ user, onEdit, className }: UserProfileCardProps) {
return (
<Card className={cn("p-6", className)}>
<div className="flex items-center gap-4">
<Avatar className="h-12 w-12">
<AvatarImage src={user.avatarUrl} alt={user.name} />
<AvatarFallback>{user.name.charAt(0)}</AvatarFallback>
</Avatar>
<div className="space-y-1">
<h3 className="text-sm font-medium leading-none">{user.name}</h3>
<p className="text-sm text-muted-foreground">{user.role}</p>
</div>
</div>
{onEdit && (
<div className="mt-4">
<Button
variant="outline"
size="sm"
onClick={() => onEdit(user.id)}
aria-label={`编辑${user.name}的资料`}
>
编辑资料
</Button>
</div>
)}
</Card>
);
}SaaS Dashboard Design Tokens Setup
SaaS仪表盘设计令牌设置
Tailwind config extension:
ts
// tailwind.config.ts
import type { Config } from "tailwindcss";
export default {
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
} satisfies Config;Tailwind配置扩展:
ts
// tailwind.config.ts
import type { Config } from "tailwindcss";
export default {
theme: {
extend: {
colors: {
background: "hsl(var(--background))",
foreground: "hsl(var(--foreground))",
primary: {
DEFAULT: "hsl(var(--primary))",
foreground: "hsl(var(--primary-foreground))",
},
secondary: {
DEFAULT: "hsl(var(--secondary))",
foreground: "hsl(var(--secondary-foreground))",
},
muted: {
DEFAULT: "hsl(var(--muted))",
foreground: "hsl(var(--muted-foreground))",
},
accent: {
DEFAULT: "hsl(var(--accent))",
foreground: "hsl(var(--accent-foreground))",
},
destructive: {
DEFAULT: "hsl(var(--destructive))",
foreground: "hsl(var(--destructive-foreground))",
},
border: "hsl(var(--border))",
input: "hsl(var(--input))",
ring: "hsl(var(--ring))",
},
fontFamily: {
sans: ["Inter", "system-ui", "sans-serif"],
},
borderRadius: {
lg: "var(--radius)",
md: "calc(var(--radius) - 2px)",
sm: "calc(var(--radius) - 4px)",
},
},
},
} satisfies Config;Responsive Dashboard Layout
响应式仪表盘布局
tsx
export function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen bg-background">
<nav className="border-b border-border" aria-label="Main navigation">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center">
{/* nav content */}
</div>
</nav>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 lg:grid-cols-[240px_1fr] gap-8">
<aside className="hidden lg:block" aria-label="Sidebar">
{/* sidebar content */}
</aside>
<main>{children}</main>
</div>
</div>
</div>
);
}tsx
export function DashboardLayout({ children }: { children: React.ReactNode }) {
return (
<div className="min-h-screen bg-background">
<nav className="border-b border-border" aria-label="主导航">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 h-16 flex items-center">
{/* 导航内容 */}
</div>
</nav>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
<div className="grid grid-cols-1 lg:grid-cols-[240px_1fr] gap-8">
<aside className="hidden lg:block" aria-label="侧边栏">
{/* 侧边栏内容 */}
</aside>
<main>{children}</main>
</div>
</div>
</div>
);
}Edge Cases
边缘情况
-
No existing design tokens: Generate a starter token set (see) and present it to the user for confirmation before writing any component code. Ask: "No design tokens found. Here's a starter set — should I apply these?"
references/design-tokens-reference.md -
shadcn/ui not installed: Fall back to plain Tailwind with equivalent patterns. Useinstead of
<button className="...">, styled<Button>instead of<div>. Maintain the same spacing and color token approach.<Card> -
Component overlap: If a requested component duplicates an existing one, flag it: "A similarcomponent exists at
UserCard. Should I extend it or create a separate component?"src/components/UserCard.tsx -
Dark mode tokens missing: Iftokens exist but
:rootvariants are absent, generate matching dark variants before proceeding. Every semantic color token must have both light and dark values..dark -
Custom brand colors: When the user provides specific brand hex values, convert them to HSL and integrate into the token system. Never use the hex values directly in components.
-
Inconsistent spacing in existing code: Flag the inconsistency, suggest the closest 8pt grid values, and ask whether to normalize existing components or only apply the grid to new code.
See for starter token sets, color palette guide, and typography scales.
references/design-tokens-reference.md-
无现有设计令牌:生成一套初始令牌(请参阅),并在编写组件代码之前呈现给用户确认。询问:“未找到设计令牌。这是一套初始令牌——是否应用这些设置?”
references/design-tokens-reference.md -
未安装shadcn/ui:退而使用纯Tailwind实现等效模式。用替代
<button className="...">,用带样式的<Button>替代<div>。保持相同的间距和颜色令牌使用方式。<Card> -
组件重复:如果请求的组件与现有组件重复,需提示:“在中已存在类似的
src/components/UserCard.tsx组件。是否扩展该组件还是创建新组件?”UserCard -
缺少深色模式令牌:如果令牌存在但
:root变体缺失,请在继续之前生成匹配的深色变体。每个语义化颜色令牌都必须同时包含浅色和深色值。.dark -
自定义品牌颜色:当用户提供特定品牌十六进制颜色值时,将其转换为HSL格式并集成到令牌系统中。切勿在组件中直接使用十六进制值。
-
现有代码间距不一致:指出不一致之处,建议最接近的8pt网格值,并询问是统一现有组件还是仅对新代码应用网格规范。
请参阅获取初始令牌集、调色板指南和排版比例。
references/design-tokens-reference.md