Files
nexus/Project/fonrey/UI_SYSTEM/UI_SYSTEM文档要求.md
2026-04-25 09:10:07 +08:00

14 KiB
Raw Blame History

UI_SYSTEM.md 的核心目标是:让 AI 生成的每一个组件,都像是同一个设计师写的,而不是从五个不同的 UI 库里随机拼凑的。


必须包含的内容

1. 设计哲学Design Philosophy

在写任何具体规则之前,先定义"感觉"。AI 在模糊情况下会回到这里做判断。

## 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. 设计 TokenDesign Tokens

这是整个系统的基础。所有颜色、间距、字体都必须来自这里AI 不能自己发明数值。

## 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 最需要的部分。

## 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
<Button onClick={handleSubmit} loading={isSubmitting}>
  Save Changes
</Button>

// Wrong — no loading state
<Button onClick={handleSubmit} disabled={isSubmitting}>
  {isSubmitting ? 'Saving...' : 'Save Changes'}
</Button>

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

### 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 125 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

### 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

## 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

## 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

## 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

## 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 面对"这里用什么颜色?""这个按钮多大?""错误怎么展示?"时,答案必须在这里找到,不能靠猜。