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