`UI_SYSTEM.md` 的核心目标是:**让 AI 生成的每一个组件,都像是同一个设计师写的,而不是从五个不同的 UI 库里随机拼凑的。**
---
## 必须包含的内容
### 1. 设计哲学(Design Philosophy)
在写任何具体规则之前,先定义"感觉"。AI 在模糊情况下会回到这里做判断。
```md
## Design Philosophy
**Core aesthetic**: Clean, functional, low-friction.
We build tools, not experiences. Every UI element must earn its place.
**Principles** (in priority order):
1. **Clarity over cleverness** — if you have to explain the UI, it failed
2. **Density over whitespace** — our users are power users, don't waste screen space
3. **Consistency over novelty** — use existing patterns before inventing new ones
4. **Motion is functional** — animate only to communicate state change, never for decoration
**Anti-patterns we actively avoid**:
- Skeleton loaders for data that loads in < 300ms (just show a spinner)
- Modal dialogs for destructive actions that are easily reversible
- Infinite scroll (we use pagination, users need to share URLs to specific pages)
- Tooltips on mobile
```
---
### 2. 设计 Token(Design Tokens)
这是整个系统的基础。所有颜色、间距、字体都必须来自这里,AI 不能自己发明数值。
````md
## Design Tokens
### Color System
We use CSS variables. NEVER use raw hex values in components.
**Semantic colors** (use these, not primitives):
```css
--color-bg-base /* page background */
--color-bg-subtle /* card, sidebar backgrounds */
--color-bg-muted /* disabled states, placeholders */
--color-text-primary /* body text */
--color-text-secondary /* labels, captions */
--color-text-disabled /* disabled text */
--color-text-inverse /* text on dark backgrounds */
--color-border /* default borders */
--color-border-strong /* focused, emphasized borders */
--color-accent /* primary actions, links */
--color-accent-hover /* hover state of accent */
--color-success /* confirmations, completed states */
--color-warning /* non-blocking alerts */
--color-danger /* destructive actions, errors */
--color-info /* informational, neutral alerts */
````
**Rule**: If you find yourself writing `text-gray-500`, stop. Map it to a semantic token.
### Spacing Scale
We use an 4px base grid. Only use these values: `4px / 8px / 12px / 16px / 24px / 32px / 48px / 64px / 96px`
In Tailwind: `p-1 / p-2 / p-3 / p-4 / p-6 / p-8 / p-12 / p-16 / p-24`
Never: `p-5`, `p-7`, `p-9`, `p-10`, `p-11` — these break the grid.
### Border Radius
```
--radius-sm: 4px → rounded-sm (inputs, badges)
--radius-md: 8px → rounded (cards, buttons) ← default
--radius-lg: 12px → rounded-xl (modals, panels)
--radius-full: 9999px → rounded-full (avatars, pills)
```
Never mix radius sizes within the same component.
### Elevation / Shadow
```
--shadow-sm → subtle card lift
--shadow-md → dropdowns, popovers
--shadow-lg → modals, dialogs
```
Never use `drop-shadow` filter — use `box-shadow` only.
````
---
### 3. 字体系统(Typography System)
```md
## Typography
**Font stack**:
- UI: `Inter` (loaded via next/font, variable weight)
- Code: `JetBrains Mono` (code blocks, inline code only)
- Never import fonts from Google Fonts directly
**Type scale** (use only these, no arbitrary sizes):
| Token | Size | Weight | Line-height | Usage |
|----------------|-------|--------|-------------|--------------------------|
| `text-xs` | 12px | 400 | 1.5 | Labels, badges, metadata |
| `text-sm` | 14px | 400 | 1.5 | Body, secondary content |
| `text-base` | 16px | 400 | 1.6 | Primary body text |
| `text-lg` | 18px | 500 | 1.4 | Section headings |
| `text-xl` | 20px | 600 | 1.3 | Page sub-headings |
| `text-2xl` | 24px | 700 | 1.2 | Page titles |
| `text-3xl` | 30px | 700 | 1.1 | Hero headings only |
**Rules**:
- Max 2 font sizes per component
- `font-weight: 500` is the minimum for anything interactive (buttons, links)
- Never use `text-3xl` outside of marketing pages
- Line length: max 72 characters for body text (`max-w-prose`)
````
---
### 4. 核心组件规范(Core Component Specs)
为每个高频组件定义变体、状态和使用规则。这是 AI 最需要的部分。
````md
## Core Component Specs
### Button
**Variants**:
| Variant | Use case | Never use for |
|-------------|---------------------------------------|----------------------------|
| `primary` | Single main CTA per view | Destructive actions |
| `secondary` | Secondary actions | Main CTA |
| `ghost` | Toolbar actions, low-priority | Standalone CTAs |
| `danger` | Irreversible destructive actions only | Anything reversible |
| `link` | Navigation only | Form submissions |
**Sizes**: `sm` (28px h) / `md` (36px h, default) / `lg` (44px h)
**States** (all must be handled):
- `default` / `hover` / `active` / `focus-visible` / `disabled` / `loading`
**Loading state rule**:
Show spinner + disable button immediately on click.
Never let the button be clicked twice.
```tsx
// Correct
// Wrong — no loading state
````
**Icon buttons**: Always include `aria-label`. Never use icon-only buttons for primary actions.
---
### Form Inputs
**Anatomy** (always in this order, no exceptions):
```
[Label] ← always visible, never placeholder-only
[Input field]
[Helper text] ← optional, describes expected format
[Error message] ← replaces helper text on error
```
**States**: `default` / `focus` / `error` / `disabled` / `readonly`
**Rules**:
- Label always above input, never to the side (except checkbox/radio)
- Placeholder text is NOT a label — both must exist
- Error messages: specific and actionable ("Enter a valid email" not "Invalid input")
- Required fields: mark with asterisk (*) next to label, explain at top of form
- Never disable a submit button to prevent submission — show errors inline instead
---
### Data Table
```md
### Table
**Default behavior**:
- Sticky header on scroll
- Row hover highlight
- Checkbox column for bulk actions (leftmost)
- Actions column (rightmost, visible on row hover only)
- Empty state: illustration + message + CTA (never just "No data")
**Pagination**:
- Default page size: 25 rows
- Options: 10 / 25 / 50 / 100
- Always show total count ("Showing 1–25 of 143 results")
- Preserve page position on filter change
**Column rules**:
- Numbers: right-aligned, monospace font
- Dates: relative time for < 7 days ("2 hours ago"), absolute for older
- Status: always a colored badge, never plain text
- Long text: truncate with tooltip showing full value
```
---
### Modal / Dialog
```md
### Modal
**Size variants**:
| Size | Max-width | Use case |
|-------|-----------|---------------------------|
| `sm` | 400px | Confirmation dialogs |
| `md` | 560px | Forms with < 5 fields |
| `lg` | 720px | Complex forms, previews |
| `xl` | 960px | Multi-step flows |
**Rules**:
- Always trap focus inside modal
- ESC key always closes (unless unsaved changes → show confirmation)
- Click outside closes (unless form with unsaved changes)
- Never nest modals — use a multi-step flow instead
- Destructive confirm dialogs: danger button on RIGHT, cancel on LEFT
- Never auto-close a modal after async action — wait for user to dismiss
```
---
### 5. 状态与反馈模式(State & Feedback Patterns)
````md
## State & Feedback Patterns
### Loading States
| Duration | Pattern |
|---------------|--------------------------------|
| < 300ms | Nothing (avoid flash of spinner)|
| 300ms – 1s | Inline spinner |
| 1s – 3s | Spinner + "Loading..." |
| > 3s | Progress bar + estimated time |
| Background | Subtle pulsing indicator in nav|
### Empty States
Every list/table must handle empty state:
```tsx
// Required elements:
// 1. Relevant icon (not a generic "no data" icon)
// 2. Friendly headline ("No tasks yet")
// 3. Explanation of why ("Projects with tasks will appear here")
// 4. CTA if user can fix it ("Create your first task →")
````
### Toast Notifications
|Type|When to use|Duration|
|---|---|---|
|`success`|Async action completed|3s|
|`error`|Action failed, user must retry|persistent|
|`warning`|Completed with caveats|5s|
|`info`|Background process started|3s|
**Rules**:
- Max 3 toasts visible at once (queue the rest)
- Never show success toast for page navigations
- Error toasts must include a retry action when possible
- Never use toast for validation errors — show inline instead
### Skeleton vs Spinner
- Skeleton: only for content with known layout (profile cards, feed items)
- Spinner: for unknown-shape content, buttons, inline actions
- Never both at the same time in the same view
````
---
### 6. 响应式断点(Responsive Breakpoints)
```md
## Responsive Breakpoints
**Strategy**: Desktop-first (our users are 85% desktop)
| Breakpoint | Token | Value | Target |
|------------|--------|--------|--------------------------|
| Desktop | (base) | > 1280px | Primary design target |
| Laptop | `lg` | 1024px | Minor adjustments |
| Tablet | `md` | 768px | Collapsed sidebar |
| Mobile | `sm` | 640px | Single column, no tables |
**Component-specific rules**:
- Data tables → horizontal scroll on `md` and below
- Sidebar → collapses to bottom nav on `sm`
- Modals → full-screen on `sm`
- Multi-column forms → single column on `md` and below
**Never**:
- Hide critical functionality on mobile (adapt it, don't remove it)
- Use fixed px widths for layout containers
- Assume touch input on desktop or mouse on mobile
````
---
### 7. 动效规范(Motion & Animation)
```md
## Motion & Animation
**Principle**: Motion communicates state, it doesn't decorate.
**Duration scale**:
```
--duration-fast: 100ms → micro-interactions (checkbox, toggle) --duration-normal: 200ms → most transitions (hover, focus) --duration-slow: 350ms → larger elements (modal, drawer enter) --duration-crawl: 500ms → only for page-level transitions
```
**Easing**:
```
--ease-default: cubic-bezier(0.2, 0, 0, 1) → most UI transitions --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1) → playful elements only --ease-linear: linear → progress bars only
```
**What to animate**:
- ✅ Opacity (enter/exit)
- ✅ Transform: translateY (panel slide-in)
- ✅ Max-height (accordion expand)
**Never animate**:
- ❌ `width` or `height` directly (use `max-height` or `transform`)
- ❌ `top/left/right/bottom` (use `transform: translate`)
- ❌ `box-shadow` on hover (use opacity trick instead)
- ❌ Anything if `prefers-reduced-motion: reduce`
```
---
### 8. 可访问性基线(Accessibility Baseline)
```md
## Accessibility (Non-negotiable)
**Every component must**:
- Meet WCAG 2.1 AA contrast ratios (4.5:1 body, 3:1 large text)
- Be fully keyboard navigable
- Have visible focus indicators (never `outline: none` without replacement)
- Work with screen readers (proper ARIA roles and labels)
**Required patterns**:
- Icon-only buttons: always `aria-label`
- Form inputs: always `htmlFor` ↔ `id` pairing
- Images: `alt` text always (empty string `""` for decorative images)
- Modals: `role="dialog"`, `aria-modal="true"`, focus trap
- Loading states: `aria-busy="true"` on the loading container
- Error messages: `aria-describedby` linking input to error text
**Color alone is never enough**:
- Status badges: color + icon + text
- Form errors: color + icon + message below field
- Graphs: color + pattern or label
```
---
### 9. 禁止模式(Anti-patterns)
```md
## UI Anti-patterns — Never Do These
**Layout**:
- ❌ Centering body text wider than 72 characters
- ❌ Full-width buttons on desktop (max-width: 320px)
- ❌ Mixing card and table layouts in the same list view
**Interaction**:
- ❌ Double-click to perform actions (single click only)
- ❌ Drag-and-drop as the *only* way to reorder
- ❌ Hover-only affordances (invisible until you hover)
- ❌ Auto-submitting forms on change without explicit confirmation
**Feedback**:
- ❌ Generic error messages ("Something went wrong")
- ❌ Success messages that don't tell the user what happened
- ❌ Blocking UI with a spinner for optimistic actions
- ❌ Alert dialogs (window.alert) — use our Dialog component
**Content**:
- ❌ Lorem ipsum in any committed code
- ❌ Hardcoded user names or emails in components
- ❌ Placeholder images (use our Avatar initials fallback)
```
---
## 优先级总结
|优先级|内容|为什么关键|
|---|---|---|
|🔴 必须|设计 Token(颜色、间距、圆角)|AI 最容易乱用原始数值|
|🔴 必须|核心组件规范(Button、Input、Table)|高频生成,最容易出现不一致|
|🔴 必须|状态与反馈模式|最能体现产品质感的细节|
|🟡 重要|字体系统|防止 AI 混用字号和字重|
|🟡 重要|可访问性基线|事后补救成本极高|
|🟡 重要|禁止模式|比"应该做什么"更有效|
|🟢 加分|动效规范|统一产品"手感"|
|🟢 加分|响应式断点|避免断点不一致的多设备问题|
---
**核心原则**:`UI_SYSTEM.md` 不是设计文档,是给 AI 的**决策树**。当 AI 面对"这里用什么颜色?""这个按钮多大?""错误怎么展示?"时,答案必须在这里找到,不能靠猜。