ui-web

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

UI Design Skill (Web)

网页UI设计技能(Web)

Load with: base.md + react-web.md

加载依赖:base.md + react-web.md

MANDATORY: WCAG 2.1 AA Compliance

强制要求:符合WCAG 2.1 AA标准

These rules are NON-NEGOTIABLE. Every UI element must pass these checks.
这些规则是不可协商的。每个UI元素都必须通过这些检查。

1. Color Contrast (CRITICAL)

1. 颜色对比度(关键)

Text Contrast Requirements:
├── Normal text (<18px): 4.5:1 minimum
├── Large text (≥18px bold or ≥24px): 3:1 minimum
├── UI components (buttons, inputs): 3:1 minimum
└── Focus indicators: 3:1 minimum

FORBIDDEN COLOR COMBINATIONS:
✗ gray-400 on white (#9CA3AF on #FFFFFF = 2.6:1) - FAILS
✗ gray-500 on white (#6B7280 on #FFFFFF = 4.6:1) - BARELY PASSES
✗ white on yellow - FAILS
✗ light blue on white - USUALLY FAILS

SAFE COLOR COMBINATIONS:
✓ gray-700 on white (#374151 on #FFFFFF = 9.2:1)
✓ gray-600 on white (#4B5563 on #FFFFFF = 6.4:1)
✓ gray-900 on white (#111827 on #FFFFFF = 16:1)
✓ white on gray-900, blue-600, green-700
文本对比度要求:
├── 常规文本(<18px):最低4.5:1
├── 大文本(≥18px粗体或≥24px):最低3:1
├── UI组件(按钮、输入框):最低3:1
└── 焦点指示器:最低3:1

禁止的颜色组合:
✗ 白色背景上的gray-400(#9CA3AF 搭配 #FFFFFF = 2.6:1)- 不通过
✗ 白色背景上的gray-500(#6B7280 搭配 #FFFFFF = 4.6:1)- 勉强通过
✗ 黄色背景上的白色文本 - 不通过
✗ 白色背景上的浅蓝色文本 - 通常不通过

安全的颜色组合:
✓ 白色背景上的gray-700(#374151 搭配 #FFFFFF = 9.2:1)
✓ 白色背景上的gray-600(#4B5563 搭配 #FFFFFF = 6.4:1)
✓ 白色背景上的gray-900(#111827 搭配 #FFFFFF = 16:1)
✓ gray-900、blue-600、green-700背景上的白色文本

2. Visibility Rules (CRITICAL)

2. 可见性规则(关键)

ALL BUTTONS MUST HAVE:
✓ Visible background color OR visible border (min 1px)
✓ Text color that contrasts with background
✓ Minimum height: 44px (touch target)
✓ Padding: at least px-4 py-2

NEVER CREATE:
✗ Buttons with transparent background AND no border
✗ Text same color as background
✗ Ghost buttons without visible borders
✗ White text on light backgrounds
✗ Dark text on dark backgrounds
所有按钮必须具备:
✓ 可见的背景色 或 可见的边框(最小1px)
✓ 与背景形成对比的文本颜色
✓ 最小高度:44px(触摸目标)
✓ 内边距:至少px-4 py-2

绝对不能创建:
✗ 透明背景且无边框的按钮
✗ 文本颜色与背景色相同的按钮
✗ 无可见边框的幽灵按钮
✗ 浅色背景上的白色文本
✗ 深色背景上的深色文本

3. Required Element Styles

3. 必填元素样式

tsx
// EVERY button needs visible boundaries
// PRIMARY: solid background
<button className="bg-gray-900 text-white px-4 py-3 rounded-lg">
  Primary
</button>

// SECONDARY: visible background
<button className="bg-gray-100 text-gray-900 px-4 py-3 rounded-lg">
  Secondary
</button>

// GHOST: MUST have visible border
<button className="border border-gray-300 text-gray-700 px-4 py-3 rounded-lg">
  Ghost
</button>

// NEVER DO THIS:
<button className="text-gray-500">Invisible Button</button> // ✗ NO BOUNDARY
<button className="bg-white text-white">Hidden</button>     // ✗ NO CONTRAST
tsx
// 每个按钮都需要可见的边界
// 主要按钮:实色背景
<button className="bg-gray-900 text-white px-4 py-3 rounded-lg">
  Primary
</button>

// 次要按钮:可见背景
<button className="bg-gray-100 text-gray-900 px-4 py-3 rounded-lg">
  Secondary
</button>

// 幽灵按钮:必须有可见边框
<button className="border border-gray-300 text-gray-700 px-4 py-3 rounded-lg">
  Ghost
</button>

// 绝对不要这样做:
<button className="text-gray-500">Invisible Button</button> // ✗ 无边界
<button className="bg-white text-white">Hidden</button>     // ✗ 无对比度

4. Focus States (REQUIRED)

4. 焦点状态(必填)

tsx
// EVERY interactive element needs visible focus
className="focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"

// NEVER remove focus without replacement
className="outline-none" // ✗ FORBIDDEN without ring replacement
tsx
// 所有可交互元素都需要可见的焦点状态
className="focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2"

// 绝对不要在没有替代方案的情况下移除焦点样式
className="outline-none" // ✗ 没有环形替代的情况下禁止使用

5. Dark Mode Contrast

5. 深色模式对比度

When implementing dark mode:
├── Text must be light (gray-100 to white) on dark backgrounds
├── Borders must be visible (gray-700 or lighter)
├── Never use gray-400 text on gray-900 bg (fails contrast)
└── Test BOTH modes before shipping

SAFE DARK MODE TEXT:
✓ text-white on bg-gray-900
✓ text-gray-100 on bg-gray-800
✓ text-gray-200 on bg-gray-900

UNSAFE (FAILS CONTRAST):
✗ text-gray-500 on bg-gray-900 (2.4:1)
✗ text-gray-400 on bg-gray-800 (3.1:1)

实现深色模式时:
├── 深色背景上的文本必须为浅色(gray-100到白色)
├── 边框必须可见(gray-700或更浅)
├── 绝对不要在gray-900背景上使用gray-400文本(对比度不达标)
└── 上线前测试两种模式

安全的深色模式文本:
✓ bg-gray-900背景上的text-white
✓ bg-gray-800背景上的text-gray-100
✓ bg-gray-900背景上的text-gray-200

不安全(对比度不达标):
✗ bg-gray-900背景上的text-gray-500(2.4:1)
✗ bg-gray-800背景上的text-gray-400(3.1:1)

Core Philosophy

核心理念

Beautiful UI is not decoration - it's communication. Every visual choice should serve clarity, hierarchy, and user confidence. Default to elegance and restraint.
美观的UI不是装饰——而是沟通。每一个视觉选择都应该服务于清晰度、层级结构和用户信任感。优先选择优雅和克制的设计。

Design Principles

设计原则

1. Visual Hierarchy

1. 视觉层级

Primary Action    → Bold, high contrast, prominent
Secondary Action  → Subtle, lower contrast
Tertiary/Links    → Minimal, text-style
主要操作    → 粗体、高对比度、突出显示
次要操作  → 柔和、低对比度
三级操作/链接    → 极简、文本样式

2. Spacing System (8px Grid)

2. 间距系统(8px网格)

typescript
// Tailwind spacing scale - USE CONSISTENTLY
const spacing = {
  xs: 'p-1',      // 4px  - tight internal
  sm: 'p-2',      // 8px  - compact
  md: 'p-4',      // 16px - default
  lg: 'p-6',      // 24px - comfortable
  xl: 'p-8',      // 32px - spacious
  '2xl': 'p-12',  // 48px - section gaps
};

// Rule: More whitespace = more premium feel
// Rule: Consistent spacing > perfect spacing
typescript
// Tailwind间距刻度 - 保持一致使用
const spacing = {
  xs: 'p-1',      // 4px  - 紧凑内部间距
  sm: 'p-2',      // 8px  - 紧凑型
  md: 'p-4',      // 16px - 默认
  lg: 'p-6',      // 24px - 舒适型
  xl: 'p-8',      // 32px - 宽敞型
  '2xl': 'p-12',  // 48px - 区块间距
};

// 规则:留白越多,质感越高级
// 规则:间距一致性 > 完美间距

3. Typography Scale

3. 排版刻度

typescript
// Limit to 3-4 font sizes per page
const typography = {
  hero: 'text-4xl md:text-5xl font-bold tracking-tight',
  heading: 'text-2xl md:text-3xl font-semibold',
  subheading: 'text-lg md:text-xl font-medium',
  body: 'text-base leading-relaxed',
  caption: 'text-sm text-gray-500',
};

// Rule: Never use more than 2 font families
// Rule: Line height 1.5-1.7 for body text
typescript
// 每页限制使用3-4种字体大小
const typography = {
  hero: 'text-4xl md:text-5xl font-bold tracking-tight',
  heading: 'text-2xl md:text-3xl font-semibold',
  subheading: 'text-lg md:text-xl font-medium',
  body: 'text-base leading-relaxed',
  caption: 'text-sm text-gray-500',
};

// 规则:绝对不要使用超过2种字体
// 规则:正文文本行高1.5-1.7

Glassmorphism (Web)

毛玻璃效果(Web)

Base Glass Card

基础毛玻璃卡片

tsx
// Modern glass effect - use sparingly for emphasis
const GlassCard = ({ children, className = '' }) => (
  <div className={`
    backdrop-blur-xl
    bg-white/10
    border border-white/20
    rounded-2xl
    shadow-xl
    shadow-black/5
    ${className}
  `}>
    {children}
  </div>
);
tsx
// 现代毛玻璃效果 - 谨慎使用以突出重点
const GlassCard = ({ children, className = '' }) => (
  <div className={`
    backdrop-blur-xl
    bg-white/10
    border border-white/20
    rounded-2xl
    shadow-xl
    shadow-black/5
    ${className}
  `}>
    {children}
  </div>
);

Glass Variants

毛玻璃变体

tsx
// Light mode glass
const lightGlass = `
  backdrop-blur-xl
  bg-white/70
  border border-white/50
  shadow-lg shadow-gray-200/50
`;

// Dark mode glass
const darkGlass = `
  backdrop-blur-xl
  bg-gray-900/70
  border border-white/10
  shadow-xl shadow-black/20
`;

// Frosted sidebar
const frostedSidebar = `
  backdrop-blur-2xl
  bg-gradient-to-b from-white/80 to-white/60
  border-r border-white/30
`;

// Floating action glass
const floatingGlass = `
  backdrop-blur-md
  bg-white/90
  rounded-full
  shadow-lg shadow-black/10
  border border-white/50
`;
tsx
// 浅色模式毛玻璃
const lightGlass = `
  backdrop-blur-xl
  bg-white/70
  border border-white/50
  shadow-lg shadow-gray-200/50
`;

// 深色模式毛玻璃
const darkGlass = `
  backdrop-blur-xl
  bg-gray-900/70
  border border-white/10
  shadow-xl shadow-black/20
`;

// 磨砂侧边栏
const frostedSidebar = `
  backdrop-blur-2xl
  bg-gradient-to-b from-white/80 to-white/60
  border-r border-white/30
`;

// 悬浮操作毛玻璃
const floatingGlass = `
  backdrop-blur-md
  bg-white/90
  rounded-full
  shadow-lg shadow-black/10
  border border-white/50
`;

When to Use Glassmorphism

何时使用毛玻璃效果

✓ Hero sections with image backgrounds
✓ Floating cards over gradients
✓ Modal overlays
✓ Navigation bars (subtle)
✓ Feature highlights

✗ Every card (overuse kills the effect)
✗ Text-heavy content areas
✗ Forms (reduces contrast)
✗ Data tables
✓ 带图片背景的Hero区块
✓ 渐变背景上的悬浮卡片
✓ 模态框遮罩
✓ 导航栏(柔和效果)
✓ 功能亮点

✗ 所有卡片都使用(过度使用会失去效果)
✗ 文本密集的内容区域
✗ 表单(降低对比度)
✗ 数据表格

Color System

颜色系统

Semantic Colors

语义化颜色

typescript
const colors = {
  // Actions
  primary: 'bg-blue-600 hover:bg-blue-700',
  secondary: 'bg-gray-100 hover:bg-gray-200 text-gray-900',
  danger: 'bg-red-600 hover:bg-red-700',
  success: 'bg-green-600 hover:bg-green-700',

  // Surfaces
  background: 'bg-gray-50 dark:bg-gray-950',
  surface: 'bg-white dark:bg-gray-900',
  elevated: 'bg-white dark:bg-gray-800 shadow-lg',

  // Text
  textPrimary: 'text-gray-900 dark:text-white',
  textSecondary: 'text-gray-600 dark:text-gray-400',
  textMuted: 'text-gray-400 dark:text-gray-500',
};
typescript
const colors = {
  // 操作类
  primary: 'bg-blue-600 hover:bg-blue-700',
  secondary: 'bg-gray-100 hover:bg-gray-200 text-gray-900',
  danger: 'bg-red-600 hover:bg-red-700',
  success: 'bg-green-600 hover:bg-green-700',

  // 表面类
  background: 'bg-gray-50 dark:bg-gray-950',
  surface: 'bg-white dark:bg-gray-900',
  elevated: 'bg-white dark:bg-gray-800 shadow-lg',

  // 文本类
  textPrimary: 'text-gray-900 dark:text-white',
  textSecondary: 'text-gray-600 dark:text-gray-400',
  textMuted: 'text-gray-400 dark:text-gray-500',
};

Gradient Backgrounds

渐变背景

tsx
// Subtle mesh gradient (modern, premium)
const meshGradient = `
  bg-gradient-to-br
  from-blue-50 via-white to-purple-50
  dark:from-gray-950 dark:via-gray-900 dark:to-gray-950
`;

// Vibrant hero gradient
const heroGradient = `
  bg-gradient-to-r
  from-blue-600 via-purple-600 to-pink-600
`;

// Subtle radial glow
const radialGlow = `
  bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))]
  from-blue-200/40 via-transparent to-transparent
`;
tsx
// 柔和的网格渐变(现代、高级)
const meshGradient = `
  bg-gradient-to-br
  from-blue-50 via-white to-purple-50
  dark:from-gray-950 dark:via-gray-900 dark:to-gray-950
`;

// 鲜艳的Hero渐变
const heroGradient = `
  bg-gradient-to-r
  from-blue-600 via-purple-600 to-pink-600
`;

// 柔和的径向发光
const radialGlow = `
  bg-[radial-gradient(ellipse_at_top,_var(--tw-gradient-stops))]
  from-blue-200/40 via-transparent to-transparent
`;

Component Patterns

组件模式

Buttons

按钮

tsx
// Primary button - bold, confident
const PrimaryButton = ({ children, ...props }) => (
  <button
    className="
      px-6 py-3
      bg-gray-900 dark:bg-white
      text-white dark:text-gray-900
      font-medium
      rounded-xl
      transition-all duration-200
      hover:bg-gray-800 dark:hover:bg-gray-100
      hover:shadow-lg hover:shadow-gray-900/20
      active:scale-[0.98]
      disabled:opacity-50 disabled:cursor-not-allowed
    "
    {...props}
  >
    {children}
  </button>
);

// Secondary button - subtle
const SecondaryButton = ({ children, ...props }) => (
  <button
    className="
      px-6 py-3
      bg-gray-100 dark:bg-gray-800
      text-gray-900 dark:text-white
      font-medium
      rounded-xl
      transition-all duration-200
      hover:bg-gray-200 dark:hover:bg-gray-700
      active:scale-[0.98]
    "
    {...props}
  >
    {children}
  </button>
);

// Ghost button - minimal
const GhostButton = ({ children, ...props }) => (
  <button
    className="
      px-4 py-2
      text-gray-600 dark:text-gray-400
      font-medium
      rounded-lg
      transition-colors duration-200
      hover:text-gray-900 dark:hover:text-white
      hover:bg-gray-100 dark:hover:bg-gray-800
    "
    {...props}
  >
    {children}
  </button>
);
tsx
// 主要按钮 - 醒目、自信
const PrimaryButton = ({ children, ...props }) => (
  <button
    className="
      px-6 py-3
      bg-gray-900 dark:bg-white
      text-white dark:text-gray-900
      font-medium
      rounded-xl
      transition-all duration-200
      hover:bg-gray-800 dark:hover:bg-gray-100
      hover:shadow-lg hover:shadow-gray-900/20
      active:scale-[0.98]
      disabled:opacity-50 disabled:cursor-not-allowed
    "
    {...props}
  >
    {children}
  </button>
);

// 次要按钮 - 柔和
const SecondaryButton = ({ children, ...props }) => (
  <button
    className="
      px-6 py-3
      bg-gray-100 dark:bg-gray-800
      text-gray-900 dark:text-white
      font-medium
      rounded-xl
      transition-all duration-200
      hover:bg-gray-200 dark:hover:bg-gray-700
      active:scale-[0.98]
    "
    {...props}
  >
    {children}
  </button>
);

// 幽灵按钮 - 极简
const GhostButton = ({ children, ...props }) => (
  <button
    className="
      px-4 py-2
      text-gray-600 dark:text-gray-400
      font-medium
      rounded-lg
      transition-colors duration-200
      hover:text-gray-900 dark:hover:text-white
      hover:bg-gray-100 dark:hover:bg-gray-800
    "
    {...props}
  >
    {children}
  </button>
);

Cards

卡片

tsx
// Clean card with subtle elevation
const Card = ({ children, className = '' }) => (
  <div className={`
    bg-white dark:bg-gray-900
    rounded-2xl
    border border-gray-200 dark:border-gray-800
    shadow-sm
    hover:shadow-md
    transition-shadow duration-300
    ${className}
  `}>
    {children}
  </div>
);

// Interactive card
const InteractiveCard = ({ children, onClick }) => (
  <button
    onClick={onClick}
    className="
      w-full text-left
      bg-white dark:bg-gray-900
      rounded-2xl
      border border-gray-200 dark:border-gray-800
      p-6
      transition-all duration-300
      hover:border-gray-300 dark:hover:border-gray-700
      hover:shadow-lg
      hover:-translate-y-1
      active:scale-[0.99]
    "
  >
    {children}
  </button>
);
tsx
// 简洁卡片,带柔和的层次感
const Card = ({ children, className = '' }) => (
  <div className={`
    bg-white dark:bg-gray-900
    rounded-2xl
    border border-gray-200 dark:border-gray-800
    shadow-sm
    hover:shadow-md
    transition-shadow duration-300
    ${className}
  `}>
    {children}
  </div>
);

// 可交互卡片
const InteractiveCard = ({ children, onClick }) => (
  <button
    onClick={onClick}
    className="
      w-full text-left
      bg-white dark:bg-gray-900
      rounded-2xl
      border border-gray-200 dark:border-gray-800
      p-6
      transition-all duration-300
      hover:border-gray-300 dark:hover:border-gray-700
      hover:shadow-lg
      hover:-translate-y-1
      active:scale-[0.99]
    "
  >
    {children}
  </button>
);

Input Fields

输入框

tsx
const Input = ({ label, error, ...props }) => (
  <div className="space-y-2">
    {label && (
      <label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
        {label}
      </label>
    )}
    <input
      className={`
        w-full px-4 py-3
        bg-gray-50 dark:bg-gray-800
        border-2 rounded-xl
        text-gray-900 dark:text-white
        placeholder-gray-400 dark:placeholder-gray-500
        transition-all duration-200
        focus:outline-none focus:ring-0
        ${error
          ? 'border-red-500 focus:border-red-500'
          : 'border-transparent focus:border-blue-500 focus:bg-white dark:focus:bg-gray-900'
        }
      `}
      {...props}
    />
    {error && (
      <p className="text-sm text-red-500">{error}</p>
    )}
  </div>
);
tsx
const Input = ({ label, error, ...props }) => (
  <div className="space-y-2">
    {label && (
      <label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
        {label}
      </label>
    )}
    <input
      className={`
        w-full px-4 py-3
        bg-gray-50 dark:bg-gray-800
        border-2 rounded-xl
        text-gray-900 dark:text-white
        placeholder-gray-400 dark:placeholder-gray-500
        transition-all duration-200
        focus:outline-none focus:ring-0
        ${error
          ? 'border-red-500 focus:border-red-500'
          : 'border-transparent focus:border-blue-500 focus:bg-white dark:focus:bg-gray-900'
        }
      `}
      {...props}
    />
    {error && (
      <p className="text-sm text-red-500">{error}</p>
    )}
  </div>
);

Micro-Interactions

微交互

Transitions

过渡动画

typescript
// Standard transitions - ALWAYS use
const transitions = {
  fast: 'transition-all duration-150',      // Hover states
  normal: 'transition-all duration-200',    // Most interactions
  slow: 'transition-all duration-300',      // Card hovers, modals
  spring: 'transition-all duration-500 ease-out', // Page transitions
};

// Rule: Everything interactive should transition
// Rule: 150-300ms feels responsive, >500ms feels slow
typescript
// 标准过渡动画 - 务必使用
const transitions = {
  fast: 'transition-all duration-150',      // 悬停状态
  normal: 'transition-all duration-200',    // 大多数交互
  slow: 'transition-all duration-300',      // 卡片悬停、模态框
  spring: 'transition-all duration-500 ease-out', // 页面过渡
};

// 规则:所有可交互元素都应该有过渡动画
// 规则:150-300ms的动画响应迅速,>500ms会感觉缓慢

Hover Effects

悬停效果

tsx
// Scale on hover (buttons, cards)
className="hover:scale-105 active:scale-95 transition-transform"

// Lift on hover (cards)
className="hover:-translate-y-1 hover:shadow-xl transition-all"

// Glow on hover (CTAs)
className="hover:shadow-lg hover:shadow-blue-500/25 transition-shadow"

// Border highlight (inputs, cards)
className="hover:border-gray-300 transition-colors"
tsx
// 悬停时缩放(按钮、卡片)
className="hover:scale-105 active:scale-95 transition-transform"

// 悬停时抬起(卡片)
className="hover:-translate-y-1 hover:shadow-xl transition-all"

// 悬停时发光(主要行动按钮)
className="hover:shadow-lg hover:shadow-blue-500/25 transition-shadow"

// 悬停时边框高亮(输入框、卡片)
className="hover:border-gray-300 transition-colors"

Loading States

加载状态

tsx
// Skeleton loader
const Skeleton = ({ className = '' }) => (
  <div className={`
    animate-pulse
    bg-gray-200 dark:bg-gray-800
    rounded-lg
    ${className}
  `} />
);

// Spinner
const Spinner = ({ size = 'md' }) => (
  <div className={`
    animate-spin rounded-full
    border-2 border-gray-200 dark:border-gray-700
    border-t-blue-600
    ${size === 'sm' ? 'w-4 h-4' : size === 'lg' ? 'w-8 h-8' : 'w-6 h-6'}
  `} />
);

// Button loading state
<button disabled className="relative">
  <span className="opacity-0">Submit</span>
  <Spinner className="absolute inset-0 m-auto" />
</button>
tsx
// 骨架加载器
const Skeleton = ({ className = '' }) => (
  <div className={`
    animate-pulse
    bg-gray-200 dark:bg-gray-800
    rounded-lg
    ${className}
  `} />
);

// 加载指示器
const Spinner = ({ size = 'md' }) => (
  <div className={`
    animate-spin rounded-full
    border-2 border-gray-200 dark:border-gray-700
    border-t-blue-600
    ${size === 'sm' ? 'w-4 h-4' : size === 'lg' ? 'w-8 h-8' : 'w-6 h-6'}
  `} />
);

// 按钮加载状态
<button disabled className="relative">
  <span className="opacity-0">提交</span>
  <Spinner className="absolute inset-0 m-auto" />
</button>

Layout Patterns

布局模式

Container

容器

tsx
// Consistent max-width and padding
const Container = ({ children, className = '' }) => (
  <div className={`
    max-w-7xl mx-auto
    px-4 sm:px-6 lg:px-8
    ${className}
  `}>
    {children}
  </div>
);
tsx
// 一致的最大宽度和内边距
const Container = ({ children, className = '' }) => (
  <div className={`
    max-w-7xl mx-auto
    px-4 sm:px-6 lg:px-8
    ${className}
  `}>
    {children}
  </div>
);

Section Spacing

区块间距

tsx
// Consistent vertical rhythm
const Section = ({ children }) => (
  <section className="py-16 md:py-24">
    <Container>{children}</Container>
  </section>
);
tsx
// 一致的垂直节奏
const Section = ({ children }) => (
  <section className="py-16 md:py-24">
    <Container>{children}</Container>
  </section>
);

Grid Systems

网格系统

tsx
// Feature grid
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {features.map(f => <FeatureCard key={f.id} {...f} />)}
</div>

// Bento grid (modern asymmetric)
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
  <div className="col-span-2 row-span-2">Large</div>
  <div className="col-span-1">Small</div>
  <div className="col-span-1">Small</div>
  <div className="col-span-2">Medium</div>
</div>
tsx
// 功能网格
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
  {features.map(f => <FeatureCard key={f.id} {...f} />)}
</div>

// 便当盒网格(现代非对称)
<div className="grid grid-cols-2 md:grid-cols-4 gap-4">
  <div className="col-span-2 row-span-2">大区块</div>
  <div className="col-span-1">小区块</div>
  <div className="col-span-1">小区块</div>
  <div className="col-span-2">中区块</div>
</div>

Dark Mode

深色模式

Implementation

实现方式

tsx
// Always design for both modes
// Use CSS variables or Tailwind dark: prefix

// Theme toggle
const ThemeToggle = () => {
  const [dark, setDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', dark);
  }, [dark]);

  return (
    <button onClick={() => setDark(!dark)}>
      {dark ? <SunIcon /> : <MoonIcon />}
    </button>
  );
};
tsx
// 始终为两种模式设计
// 使用CSS变量或Tailwind的dark:前缀

// 主题切换器
const ThemeToggle = () => {
  const [dark, setDark] = useState(false);

  useEffect(() => {
    document.documentElement.classList.toggle('dark', dark);
  }, [dark]);

  return (
    <button onClick={() => setDark(!dark)}>
      {dark ? <SunIcon /> : <MoonIcon />}
    </button>
  );
};

Color Pairing

颜色配对

Light Mode          Dark Mode
─────────────────────────────────
white               gray-950
gray-50             gray-900
gray-100            gray-800
gray-200            gray-700
gray-900 (text)     white (text)
gray-600 (secondary) gray-400
blue-600            blue-500
浅色模式          深色模式
─────────────────────────────────
white               gray-950
gray-50             gray-900
gray-100            gray-800
gray-200            gray-700
gray-900(文本)     white(文本)
gray-600(次要文本) gray-400
blue-600            blue-500

Accessibility

无障碍访问

Contrast Requirements

对比度要求

WCAG AA: 4.5:1 for normal text, 3:1 for large text
WCAG AAA: 7:1 for normal text, 4.5:1 for large text

// Test: Use browser devtools or contrast checker
// Rule: Never use gray-400 on white for body text
WCAG AA:常规文本4.5:1,大文本3:1
WCAG AAA:常规文本7:1,大文本4.5:1

// 测试方法:使用浏览器开发者工具或对比度检查器
// 规则:绝对不要在白色背景上使用gray-400作为正文文本

Focus States

焦点状态

tsx
// Always visible focus rings
className="
  focus:outline-none
  focus-visible:ring-2
  focus-visible:ring-blue-500
  focus-visible:ring-offset-2
"

// Never remove focus styles without replacement
// ✗ outline-none (alone)
// ✓ outline-none + focus-visible:ring
tsx
// 始终显示可见的焦点环
className="
  focus:outline-none
  focus-visible:ring-2
  focus-visible:ring-blue-500
  focus-visible:ring-offset-2
"

// 绝对不要在没有替代方案的情况下移除焦点样式
// ✗ 单独使用outline-none
// ✓ outline-none + focus-visible:ring

Screen Readers

屏幕阅读器

tsx
// Visually hidden but accessible
const srOnly = "absolute w-px h-px p-0 -m-px overflow-hidden whitespace-nowrap border-0";

// Icon buttons need labels
<button aria-label="Close menu">
  <XIcon className="w-6 h-6" />
</button>

// Announce dynamic content
<div role="status" aria-live="polite">
  {message}
</div>
tsx
// 视觉隐藏但可访问
const srOnly = "absolute w-px h-px p-0 -m-px overflow-hidden whitespace-nowrap border-0";

// 图标按钮需要标签
<button aria-label="关闭菜单">
  <XIcon className="w-6 h-6" />
</button>

// 通知动态内容
<div role="status" aria-live="polite">
  {message}
</div>

Anti-Patterns

反模式

Never Do

绝对不要做的事

✗ More than 3 font sizes on a page
✗ Random spacing values (use 8px grid)
✗ Pure black (#000) on pure white (#fff)
✗ Colored text on colored backgrounds without checking contrast
✗ Animations longer than 500ms for UI elements
✗ Glassmorphism everywhere
✗ Drop shadows on everything
✗ Gradients on text (hard to read)
✗ Auto-playing animations that can't be stopped
✗ Removing focus indicators
✗ Gray text below 4.5:1 contrast
✗ Tiny click targets (< 44px)
✗ 一页使用超过3种字体大小
✗ 随机的间距值(使用8px网格)
✗ 纯白(#fff)背景上的纯黑(#000)文本
✗ 不检查对比度就使用彩色文本搭配彩色背景
✗ UI元素的动画时长超过500ms
✗ 所有地方都使用毛玻璃效果
✗ 所有元素都添加投影
✗ 文本使用渐变(难以阅读)
✗ 自动播放且无法停止的动画
✗ 移除焦点指示器
✗ 对比度低于4.5:1的灰色文本
✗ 过小的点击目标(<44px)

Common Mistakes

常见错误

tsx
// ✗ Too many shadows
className="shadow-sm shadow-md shadow-lg" // Pick ONE

// ✗ Inconsistent rounding
className="rounded-sm rounded-lg rounded-2xl" // System: sm, lg, xl, 2xl

// ✗ Competing focal points
// One primary CTA per viewport

// ✗ Over-decorated
// If it doesn't serve function, remove it
tsx
// ✗ 过多的阴影
className="shadow-sm shadow-md shadow-lg" // 选一个即可

// ✗ 不一致的圆角
className="rounded-sm rounded-lg rounded-2xl" // 系统可选:sm, lg, xl, 2xl

// ✗ 相互竞争的焦点
// 每个视口内只有一个主要行动按钮

// ✗ 过度装饰
// 如果没有实际功能,就移除它

Quick Reference

快速参考

Modern Defaults

现代默认值

tsx
// Border radius: 12-16px (rounded-xl to rounded-2xl)
// Shadow: subtle (shadow-sm to shadow-md)
// Font: Inter, SF Pro, system-ui
// Primary: Near-black or brand color
// Transitions: 200ms ease-out
// Spacing: 8px grid (Tailwind default)
tsx
// 圆角:12-16px(rounded-xl到rounded-2xl)
// 阴影:柔和的(shadow-sm到shadow-md)
// 字体:Inter、SF Pro、system-ui
// 主色调:近黑色或品牌色
// 过渡动画:200ms ease-out
// 间距:8px网格(Tailwind默认)

Premium Feel Checklist

高级质感检查清单

□ Generous whitespace
□ Subtle shadows (not harsh)
□ Smooth transitions on all interactions
□ Consistent border radius
□ Limited color palette (2-3 colors max)
□ Typography hierarchy (3 sizes max)
□ High-quality imagery
□ Micro-interactions on hover/focus
□ Dark mode support
□ 充足的留白
□ 柔和的阴影(而非生硬)
□ 所有交互都有流畅的过渡动画
□ 一致的圆角
□ 有限的调色板(最多2-3种颜色)
□ 清晰的排版层级(最多3种大小)
□ 高质量的图片
□ 悬停/焦点时的微交互
□ 支持深色模式