ui-design-system

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UI 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:
  1. Read
    tailwind.config.ts
    (or
    .js
    ) for custom theme extensions
  2. Read
    src/styles/globals.css
    or
    app/globals.css
    for CSS custom properties
  3. Read
    components.json
    if shadcn/ui is configured
If no design tokens exist, generate a starter set and ask the user to confirm before proceeding (see Edge Cases).
在生成任何UI代码之前,请检查项目中的现有令牌:
  1. 读取
    tailwind.config.ts
    (或
    .js
    )中的自定义主题扩展
  2. 读取
    src/styles/globals.css
    app/globals.css
    中的CSS自定义属性
  3. 如果已配置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-foreground
    ,
    border-border
  • Never use raw Tailwind palette colors (
    bg-blue-500
    ) in component code
  • Every color must have a dark mode variant defined
  • Use
    foreground
    variants for text on colored backgrounds
将颜色定义为供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-foreground
    border-border
  • 切勿在组件代码中使用原始Tailwind调色板颜色(如
    bg-blue-500
  • 每种颜色都必须定义深色模式变体
  • 在彩色背景上的文本请使用
    foreground
    变体

Typography Scale

排版比例

Define a typographic scale using Tailwind's font-size utilities:
TokenSizeLine HeightUsage
text-xs
12px16pxCaptions, helper text
text-sm
14px20pxSecondary text, labels
text-base
16px24pxBody text (default)
text-lg
18px28pxSubheadings
text-xl
20px28pxSection headings
text-2xl
24px32pxPage headings
text-3xl
30px36pxHero headings
Typography rules:
  • Set a base font in
    tailwind.config.ts
    :
    fontFamily: { sans: ["Inter", "system-ui", "sans-serif"] }
  • Use
    font-medium
    (500) for headings and labels,
    font-normal
    (400) for body
  • Use
    tracking-tight
    for headings
    text-2xl
    and above
  • Limit line length with
    max-w-prose
    (65ch) for readability
使用Tailwind的字体大小工具定义排版比例:
令牌尺寸行高用途
text-xs
12px16px说明文字、辅助文本
text-sm
14px20px次要文本、标签
text-base
16px24px正文文本(默认)
text-lg
18px28px子标题
text-xl
20px28px章节标题
text-2xl
24px32px页面标题
text-3xl
30px36px英雄区标题
排版规则:
  • tailwind.config.ts
    中设置基础字体:
    fontFamily: { sans: ["Inter", "system-ui", "sans-serif"] }
  • 标题和标签使用
    font-medium
    (500字重),正文使用
    font-normal
    (400字重)
  • text-2xl
    及以上的标题使用
    tracking-tight
    字间距
  • 使用
    max-w-prose
    (65字符)限制行宽以提升可读性

Spacing (8pt Grid)

间距(8pt网格)

All spacing values follow an 8pt base grid:
Tailwind ClassValueUse Case
p-1
/
gap-1
4pxInline icon padding, tight gaps
p-2
/
gap-2
8pxCompact element spacing
p-3
/
gap-3
12pxInput padding, small card padding
p-4
/
gap-4
16pxStandard component padding
p-6
/
gap-6
24pxCard padding, section gaps
p-8
/
gap-8
32pxSection padding
p-12
/
gap-12
48pxPage section spacing
p-16
/
gap-16
64pxMajor layout spacing
Spacing rules:
  • Use
    gap-*
    for flex/grid children instead of individual margins
  • Prefer
    space-y-*
    for vertical stacking of sibling elements
  • Cards:
    p-6
    padding with
    gap-4
    between internal elements
  • Page sections:
    py-12
    or
    py-16
    vertical padding
  • Never mix spacing systems (no
    margin: 13px
    )
所有间距值遵循8pt基础网格:
Tailwind类数值使用场景
p-1
/
gap-1
4px内联图标内边距、紧凑间距
p-2
/
gap-2
8px紧凑元素间距
p-3
/
gap-3
12px输入框内边距、小卡片内边距
p-4
/
gap-4
16px标准组件内边距
p-6
/
gap-6
24px卡片内边距、章节间距
p-8
/
gap-8
32px章节内边距
p-12
/
gap-12
48px页面章节间距
p-16
/
gap-16
64px主要布局间距
间距规则:
  • 对于flex/grid子元素,使用
    gap-*
    而非单独的外边距
  • 垂直堆叠兄弟元素时优先使用
    space-y-*
  • 卡片:使用
    p-6
    内边距,内部元素间距为
    gap-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:
ElementUse ForNot
<button>
Clickable actions
<div onClick>
<a>
Navigation links
<button>
for links
<nav>
Navigation regions
<div>
<main>
Primary page content
<div>
<article>
Self-contained content (card, post)
<div>
<section>
Thematic grouping with heading
<div>
<aside>
Sidebar or tangential content
<div>
<header>
Introductory content for a section
<div>
<footer>
Footer content for a section
<div>
<ul>
/
<ol>
Lists of items
<div>
for each item
为每个用途使用正确的HTML元素:
元素适用场景不适用场景
<button>
可点击操作
<div onClick>
<a>
导航链接使用
<button>
实现链接
<nav>
导航区域
<div>
<main>
页面主要内容
<div>
<article>
独立内容块(卡片、文章)
<div>
<section>
带标题的主题分组
<div>
<aside>
侧边栏或次要内容
<div>
<header>
章节的介绍性内容
<div>
<footer>
章节的页脚内容
<div>
<ul>
/
<ol>
项目列表每个项目都用
<div>
包裹

shadcn/ui Primitives

shadcn/ui基础组件

Prefer shadcn/ui components over custom implementations:
NeedUseNot
Buttons
<Button>
Custom
<button>
with styles
Modals
<Dialog>
Custom modal with portal
Dropdowns
<DropdownMenu>
Custom dropdown
Cards
<Card>
Styled
<div>
Inputs
<Input>
Styled
<input>
Selects
<Select>
Native
<select>
Tooltips
<Tooltip>
Custom tooltip
Tabs
<Tabs>
Custom tab component
Tables
<Table>
Plain
<table>
Alerts
<Alert>
Custom banner div
If shadcn/ui is not installed, fall back to plain Tailwind with equivalent patterns and consistent class ordering.
优先使用shadcn/ui组件而非自定义实现:
需求推荐使用不推荐使用
按钮
<Button>
带样式的自定义
<button>
模态框
<Dialog>
带portal的自定义模态框
下拉菜单
<DropdownMenu>
自定义下拉菜单
卡片
<Card>
带样式的
<div>
输入框
<Input>
带样式的
<input>
选择器
<Select>
原生
<select>
工具提示
<Tooltip>
自定义工具提示
标签页
<Tabs>
自定义标签页组件
表格
<Table>
普通
<table>
提示框
<Alert>
自定义横幅
<div>
如果未安装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
    className?: string
    on every component for composition
  • Use
    variant
    prop for visual variations, not separate components
  • 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:
PrefixMin WidthTarget
(none)0pxMobile (default)
sm:
640pxLarge phones / small tablets
md:
768pxTablets
lg:
1024pxDesktops
xl:
1280pxLarge desktops
Responsive rules:
  • Design mobile-first: base styles for mobile, then add breakpoint overrides
  • Use
    grid-cols-1 md:grid-cols-2 lg:grid-cols-3
    for responsive grids
  • 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移动端(默认)
sm:
640px大屏手机/小平板
md:
768px平板
lg:
1024px桌面端
xl:
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:
  1. Visible label or aria-label:
    <Button aria-label="Close dialog">X</Button>
  2. Focus indicator: Tailwind's
    ring
    utilities:
    focus-visible:ring-2 focus-visible:ring-ring
  3. Keyboard access: Reachable via Tab, activatable via Enter/Space
  4. Disabled state: Both visual and
    aria-disabled
    or
    disabled
    attribute
每个交互元素必须具备:
  1. 可见标签或aria-label
    <Button aria-label="关闭对话框">X</Button>
  2. 焦点指示器:使用Tailwind的
    ring
    工具类:
    focus-visible:ring-2 focus-visible:ring-ring
  3. 键盘可访问性:可通过Tab键聚焦,通过Enter/Space键激活
  4. 禁用状态:同时具备视觉样式和
    aria-disabled
    disabled
    属性

ARIA Patterns

ARIA模式

  • Icon-only buttons:
    aria-label="Delete item"
  • Loading states:
    aria-busy="true"
    on the loading container
  • Dynamic content updates:
    aria-live="polite"
    on the container
  • Form errors:
    aria-invalid="true"
    on the input,
    role="alert"
    on the message
  • Modals:
    aria-modal="true"
    , focus trap, Escape to close
  • Navigation landmarks:
    <nav aria-label="Main navigation">
  • 仅图标按钮:
    aria-label="删除项目"
  • 加载状态:在加载容器上添加
    aria-busy="true"
  • 动态内容更新:在容器上添加
    aria-live="polite"
  • 表单错误:在输入框上添加
    aria-invalid="true"
    ,在错误消息上添加
    role="alert"
  • 模态框:
    aria-modal="true"
    、焦点捕获、按Esc键关闭
  • 导航地标:
    <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
    references/design-tokens-reference.md
    ) 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?"
  • shadcn/ui not installed: Fall back to plain Tailwind with equivalent patterns. Use
    <button className="...">
    instead of
    <Button>
    , styled
    <div>
    instead of
    <Card>
    . Maintain the same spacing and color token approach.
  • Component overlap: If a requested component duplicates an existing one, flag it: "A similar
    UserCard
    component exists at
    src/components/UserCard.tsx
    . Should I extend it or create a separate component?"
  • Dark mode tokens missing: If
    :root
    tokens exist but
    .dark
    variants are absent, generate matching dark variants before proceeding. Every semantic color token must have both light and dark values.
  • 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
references/design-tokens-reference.md
for starter token sets, color palette guide, and typography scales.
  • 无现有设计令牌:生成一套初始令牌(请参阅
    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
获取初始令牌集、调色板指南和排版比例。