interface-kit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseInterface Kit: Implementation Guide for Exceptional Interfaces
界面工具包:卓越界面实现指南
If a DESIGN.md exists at the project root, its tokens and specifications override all defaults in this skill. This skill provides sensible defaults for when no design system exists, and implementation guidance that applies regardless.
For deep dives on any section, see the reference files in this skill'sdirectory.references/
如果项目根目录存在DESIGN.md文件,其中的设计令牌和规范将覆盖本技能中的所有默认设置。当没有设计系统时,本技能提供合理的默认值,同时提供适用于所有场景的实现指导。
如需深入了解任一章节,请查看本技能目录下的参考文件。references/
1. Core Philosophy
1. 核心理念
Taste is trained, not innate. Study why great interfaces feel right. Deconstruct apps you admire — the spacing, the timing, the weight of a shadow. The gap between "fine" and "exceptional" is built from hundreds of micro-decisions that users feel but never consciously notice.
Unseen details compound. A single rounded corner, a single eased transition, a single well-chosen shadow — none of these matter alone. Together they become "a thousand barely audible voices singing in tune." The cumulative effect is what separates craft from output.
Beauty is leverage. Polish is not vanity. Good defaults, considered typography, and intentional motion are real differentiators. Users trust interfaces that feel cared for. Investors notice. Competitors can't easily replicate taste.
Intentionality over intensity. Both bold maximalism and refined minimalism work — what fails is the absence of a clear point of view. Every visual decision should trace back to a deliberate conceptual direction. If you can't articulate WHY a choice was made, reconsider it.
Choose a direction and execute with precision. Don't hedge between styles. A brutalist page committed fully will always outperform a page that's "a little bit of everything." Commit, then refine.
NEVER produce generic "AI slop" aesthetics. No gratuitous gradients on white backgrounds. No cookie-cutter hero sections with stock illustrations. No safe, forgettable layouts that could belong to any product. Every interface should have a point of view that makes it recognizable.
审美是可以训练的,并非与生俱来。研究优秀界面为何能给人舒适感,拆解你欣赏的应用——间距、过渡时长、阴影的层次感。“尚可”与“卓越”之间的差距,源自数百个用户能感知但不会刻意留意的微小决策。
细节的积累至关重要。单个圆角、一次缓动过渡、一个精心选择的阴影——单独看都无关紧要,但组合起来就会成为“上千个细微声音的和谐共鸣”。这种累积效应正是匠心与普通产出的区别所在。
美观是一种竞争力。打磨界面并非虚荣之举。合理的默认设置、考究的排版、有意图的动效都是实实在在的差异化优势。用户会信任那些看起来被用心对待的界面,投资者会注意到,竞争对手也难以轻易复制这种审美品味。
有意图胜于盲目堆砌。大胆的极简主义和精致的极简主义都能奏效——失败的是缺乏清晰的设计立场。每一个视觉决策都应追溯到明确的设计方向。如果你无法阐明某个选择的原因,请重新考虑。
选定方向并精准执行。不要在多种风格之间摇摆不定。彻底贯彻的 Brutalist(粗野主义)页面,永远比“什么风格都沾一点”的页面效果更好。选定方向后,再进行精细化打磨。
绝不要生成通用的“AI 流水线”风格界面。不要在白色背景上使用无意义的渐变,不要使用带有库存插图的千篇一律的 hero 区域,不要使用平淡无奇、可适用于任何产品的安全布局。每个界面都应有独特的设计立场,使其具有辨识度。
2. The Priority Stack
2. 优先级层级
When implementing UI, work through these priorities in order. Higher priorities are non-negotiable; lower priorities are polish that compounds quality.
| Priority | Level | What It Means |
|---|---|---|
| Accessibility | CRITICAL | Contrast 4.5:1, keyboard nav, ARIA semantics, visible focus rings. Ship nothing that excludes users. |
| Performance | HIGH | WebP/AVIF images, lazy loading below fold, CLS < 0.1, transform-only animations on the compositor thread. |
| Typography | HIGH | Font smoothing, text-wrap balance/pretty, tabular-nums for data, 65ch max line length. |
| Layout & Spatial | HIGH | 4/8px grid, concentric border radius, optical alignment over geometric. |
| Color & Theme | MEDIUM | HSL custom properties, semantic tokens, dark mode pairs tested separately. |
| Motion & Interaction | MEDIUM | Frequency-based animation decisions, 150-300ms durations, ease-out default. |
| Polish & Details | LOW | Layered shadows over borders, press feedback on buttons, staggered enter animations. |
Never skip a CRITICAL/HIGH item to chase a LOW item. A beautifully animated button that fails keyboard navigation is a net negative.
实现UI时,请按以下优先级顺序推进。高优先级内容是不可妥协的;低优先级内容是提升品质的细节打磨项。
| 优先级 | 级别 | 说明 |
|---|---|---|
| 无障碍设计 | 关键 | 对比度4.5:1、键盘导航、ARIA语义、可见焦点环。绝不能发布排斥用户的内容。 |
| 性能 | 高 | 使用WebP/AVIF图片、折叠区域懒加载、CLS<0.1、仅在合成器线程执行transform动画。 |
| 排版 | 高 | 字体平滑、文本平衡/美观换行、数据使用等宽数字、最大行宽65ch。 |
| 布局与空间设计 | 高 | 4/8px网格系统、同心圆角、视觉对齐优先于几何对齐。 |
| 色彩与主题 | 中 | HSL自定义属性、语义化令牌、单独测试深色模式配色。 |
| 动效与交互 | 中 | 基于使用频率的动效决策、150-300ms时长、默认使用ease-out缓动。 |
| 细节打磨 | 低 | 用分层阴影替代边框、按钮按压反馈、元素入场动画 stagger 效果。 |
绝不能为了追求低优先级内容而跳过关键/高优先级内容。一个动画精美但无法通过键盘导航的按钮,整体效果是负面的。
3. Aesthetic Direction
3. 美学方向
Before writing a single line of CSS, commit to a bold aesthetic direction. The most common failure mode in AI-generated UI is convergence on the same safe, forgettable look.
在编写任何CSS代码之前,先确定一个明确的美学方向。AI生成UI最常见的失败模式是趋同于安全、无记忆点的风格。
Pick a Tone
选择风格基调
Choose one and commit fully:
- Brutally minimal — generous whitespace, monospace type, stark contrast, near-zero decoration
- Maximalist chaos — layered textures, clashing type scales, dense information, intentional visual noise
- Retro-futuristic — CRT glow effects, monospace terminals, scan lines, neon on dark
- Organic / natural — earth tones, rounded shapes, paper textures, hand-drawn accents
- Luxury / refined — serif headlines, muted palettes, ample negative space, subtle gold or cream accents
- Editorial / magazine — dramatic type hierarchy, full-bleed imagery, grid-breaking layouts
- Playful / bold — bright primaries, chunky borders, exaggerated shadows, bouncy motion
选择其中一种并彻底贯彻:
- 极致极简——充足留白、等宽字体、强烈对比度、几乎无装饰
- 极繁主义——分层纹理、冲突的字体比例、密集信息、刻意的视觉噪点
- 复古未来主义——CRT发光效果、终端等宽字体、扫描线、深色背景配霓虹色
- 有机/自然风格——大地色系、圆角、纸张纹理、手绘风格装饰
- 奢华/精致风格——衬线标题字体、低饱和度配色、充足负空间、微妙的金色/奶油色装饰
- 编辑/杂志风格——夸张的字体层级、全屏图片、打破网格的布局
- 活泼/大胆风格——明亮的原色、粗边框、夸张阴影、弹性动效
Match Complexity to Vision
复杂度匹配设计愿景
Maximalist design demands elaborate code — layered backgrounds, complex grid structures, multiple font stacks. Minimalist design demands surgical precision — every pixel of spacing matters more when there's nothing to hide behind.
极繁主义设计需要复杂的代码——分层背景、复杂网格结构、多字体栈。极简主义设计需要精准的把控——当没有其他元素可以掩盖时,每一个像素的间距都至关重要。
The Ban List (When No DESIGN.md Exists)
禁用列表(无DESIGN.md时)
When building without an existing design system, avoid these overused defaults that signal "AI-generated":
- Fonts: Inter, Roboto, Arial, system-ui as display fonts, Space Grotesk
- Colors: Purple-to-blue gradients on white backgrounds
- Patterns: Generic hero with centered text + CTA + stock illustration
Vary between light and dark themes, different font pairings, different aesthetic directions. Never converge on the same choices across projects.
当没有现有设计系统,需要从零开始做美学选择时,避免使用这些被过度滥用的默认选项,它们会暴露“AI生成”的痕迹:
- 字体:Inter、Roboto、Arial、将system-ui用作展示字体、Space Grotesk
- 色彩:白色背景上的紫到蓝渐变
- 布局模式:居中文字+CTA+库存插图的通用hero区域
在不同项目中切换明暗主题、不同字体搭配、不同美学方向。绝不要在多个项目中做出相同的选择。
Visual Texture
视觉纹理
Add depth through: gradient meshes, noise/grain overlays (), layered transparencies, subtle background patterns, duotone image treatments.
filter: url(#noise)DESIGN.md overrides this entire section. If DESIGN.md specifies Inter, use Inter. If it specifies purple gradients, use them. The ban list only applies when no design system exists and you're making aesthetic choices from scratch.
通过以下方式增加深度:渐变网格、噪点/颗粒叠加()、分层透明度、微妙的背景图案、双色调图片处理。
filter: url(#noise)DESIGN.md会覆盖本节所有内容。如果DESIGN.md指定使用Inter字体,就用Inter;如果指定使用紫色渐变,就用紫色渐变。禁用列表仅适用于没有设计系统、需要从零开始做美学选择的场景。
4. Typography Essentials
4. 排版要点
Typography is the single highest-leverage design element. Get it right and mediocre layouts still feel good. Get it wrong and nothing else saves it.
排版是影响力最大的设计元素。排版做好了,平庸的布局也能给人舒适感;排版做坏了,其他任何设计都无法挽回。
Root Setup
根节点设置
css
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}Apply font smoothing to the root layout. On macOS, the default sub-pixel rendering makes text appear heavier than the designer intended.
css
html {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-rendering: optimizeLegibility;
}为根布局应用字体平滑。在macOS上,默认的子像素渲染会让文本看起来比设计师预期的更厚重。
Text Wrapping
文本换行
css
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
p, li, dd, blockquote {
text-wrap: pretty;
}balanceprettycss
h1, h2, h3, h4, h5, h6 {
text-wrap: balance;
}
p, li, dd, blockquote {
text-wrap: pretty;
}balanceprettyNumeric Display
数字显示
css
.data-value, .price, .counter, [data-numeric] {
font-variant-numeric: tabular-nums;
}Use for any number that updates dynamically — prices, counters, table columns. Without it, layout shifts as digit widths change.
tabular-numscss
.data-value, .price, .counter, [data-numeric] {
font-variant-numeric: tabular-nums;
}对于任何动态更新的数字——价格、计数器、表格列——使用。如果不使用,数字宽度变化时会导致布局偏移。
tabular-numsScale and Rhythm
比例与节奏
- Base size: 16px minimum for body text. Never go below 14px for any readable content.
- Line height: 1.5-1.75 for body text, 1.1-1.3 for large headings.
- Max line length: for body text. Long lines destroy readability.
max-width: 65ch - Type scale: Pick a consistent scale and stick to it: 12 / 14 / 16 / 18 / 24 / 32 / 48 / 64.
- 基础字号:正文文本最小16px。任何可读内容都不要小于14px。
- 行高:正文1.5-1.75,大标题1.1-1.3。
- 最大行宽:正文。过长的行宽会严重影响可读性。
max-width: 65ch - 字体比例:选择一个一致的比例并坚持使用:12 / 14 / 16 / 18 / 24 / 32 / 48 / 64。
Font Pairing
字体搭配
Pair a distinctive display font with a refined body font. The display font carries personality; the body font carries readability. Use for hierarchy within a family:
font-weight- Headings: 600-700 (semibold to bold)
- Body: 400 (regular)
- Labels / UI: 500 (medium)
Always include font stack fallbacks:
css
--font-display: "Instrument Serif", "Georgia", serif;
--font-body: "Söhne", "Helvetica Neue", sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;将有特色的展示字体与精致的正文字体搭配。展示字体传递个性;正文字体保证可读性。在同一个字体家族内使用构建层级:
font-weight- 标题:600-700(半粗体到粗体)
- 正文:400(常规)
- 标签/UI文本:500(中等粗细)
始终包含字体栈降级方案:
css
--font-display: "Instrument Serif", "Georgia", serif;
--font-body: "Söhne", "Helvetica Neue", sans-serif;
--font-mono: "JetBrains Mono", "Fira Code", monospace;5. Color & Theme
5. 色彩与主题
HSL Custom Properties (shadcn Pattern)
HSL自定义属性(shadcn模式)
css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}Define semantic tokens: primary, secondary, destructive, muted, accent, background, foreground. Reference colors by semantic name — never hardcode hex values in components.
css
:root {
--background: 0 0% 100%;
--foreground: 222.2 84% 4.9%;
--primary: 222.2 47.4% 11.2%;
--primary-foreground: 210 40% 98%;
--secondary: 210 40% 96.1%;
--secondary-foreground: 222.2 47.4% 11.2%;
--muted: 210 40% 96.1%;
--muted-foreground: 215.4 16.3% 46.9%;
--accent: 210 40% 96.1%;
--accent-foreground: 222.2 47.4% 11.2%;
--destructive: 0 84.2% 60.2%;
--destructive-foreground: 210 40% 98%;
--border: 214.3 31.8% 91.4%;
--ring: 222.2 84% 4.9%;
--radius: 0.5rem;
}定义语义化令牌:primary、secondary、destructive、muted、accent、background、foreground。通过语义名称引用颜色——绝不要在组件中硬编码十六进制值。
Dark Mode
深色模式
css
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... desaturated, lighter tonal variants — NOT simply inverted */
}Dark mode is not "invert colors." Use desaturated, lighter tonal variants. Backgrounds go dark but not pure black (). Text goes light but not pure white (). Test contrast separately for dark mode — what passes in light may fail in dark.
#000#fffcss
.dark {
--background: 222.2 84% 4.9%;
--foreground: 210 40% 98%;
/* ... 降低饱和度的浅色调变体——不是简单反转颜色 */
}深色模式不是“反转颜色”。使用降低饱和度的浅色调变体。背景色要深但不是纯黑()。文本要浅但不是纯白()。单独测试深色模式的对比度——在浅色模式下通过的对比度,在深色模式下可能不达标。
#000#fffContrast Requirements
对比度要求
- WCAG AA minimum: 4.5:1 for normal text, 3:1 for large text (18px+ bold or 24px+ regular)
- Never convey information by color alone — always pair with an icon, label, or pattern
- Test with browser devtools contrast checker or axe-core
- WCAG AA最低标准:普通文本4.5:1,大文本(18px+粗体或24px+常规)3:1
- 绝不要仅通过颜色传递信息——始终搭配图标、标签或图案
- 使用浏览器开发者工具的对比度检查器或axe-core进行测试
Color Confidence
色彩自信
Dominant colors with sharp accents outperform timid, evenly-distributed palettes. Pick one or two hero colors and let the rest of the palette recede. A confident palette has clear hierarchy; an uncertain palette spreads color evenly and feels flat.
主色调搭配鲜明的强调色,比平淡、均匀分布的配色效果更好。选择1-2个主色,让其余配色退居次要位置。自信的配色有清晰的层级;不确定的配色会均匀分布色彩,显得平淡。
6. Spatial Design
6. 空间设计
Concentric Border Radius
同心圆角
This is the single most common thing that makes nested UI elements feel "off":
outer_radius = inner_radius + paddingcss
/* Correct: concentric */
.card { border-radius: 16px; padding: 8px; }
.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */
/* Wrong: same radius on parent and child */
.card { border-radius: 12px; }
.card-inner { border-radius: 12px; } /* Looks bloated */When geometric centering looks off, align optically. Play/pause icons, dropdown carets, and asymmetric glyphs often need 1-2px manual nudges to look centered.
这是导致嵌套UI元素看起来“不协调”的最常见问题:
outer_radius = inner_radius + paddingcss
/* 正确:同心圆角 */
.card { border-radius: 16px; padding: 8px; }
.card-inner { border-radius: 8px; } /* 16 - 8 = 8 */
/* 错误:父元素和子元素圆角相同 */
.card { border-radius: 12px; }
.card-inner { border-radius: 12px; } /* 看起来臃肿 */当几何居中看起来不协调时,使用视觉对齐。播放/暂停图标、下拉箭头和不对称字形通常需要手动偏移1-2px才能看起来居中。
Shadows Over Borders
用阴影替代边框
Layer multiple transparent values for natural depth instead of using borders:
box-shadowcss
.elevated {
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.04),
0 2px 4px rgba(0, 0, 0, 0.04),
0 4px 8px rgba(0, 0, 0, 0.04);
}Multiple shadows at different spreads mimic how light works. A single hard shadow looks artificial.
使用多个透明值实现自然的层次感,而不是使用边框:
box-shadowcss
.elevated {
box-shadow:
0 1px 2px rgba(0, 0, 0, 0.04),
0 2px 4px rgba(0, 0, 0, 0.04),
0 4px 8px rgba(0, 0, 0, 0.04);
}不同扩散范围的多层阴影模拟了光线的工作方式。单个硬阴影看起来很生硬。
Image Outlines
图片轮廓
Add a subtle inset outline to images and media for consistent depth against varied backgrounds:
css
img, video {
outline: 1px solid rgba(0, 0, 0, 0.06);
outline-offset: -1px;
}为图片和媒体添加微妙的内轮廓,使其在不同背景下都能保持一致的层次感:
css
img, video {
outline: 1px solid rgba(0, 0, 0, 0.06);
outline-offset: -1px;
}Spacing Scale
间距比例
Use a 4px / 8px base incremental system. Every spacing value should be a multiple of 4:
4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128使用4px/8px的基础增量系统。所有间距值都应为4的倍数:
4 / 8 / 12 / 16 / 24 / 32 / 48 / 64 / 96 / 128Hit Areas
点击区域
Minimum 44x44px for all interactive elements. If the visual element is smaller, extend the hit area with a pseudo-element:
css
.small-button::before {
content: "";
position: absolute;
inset: -8px;
}所有交互元素的最小点击区域为44x44px。如果视觉元素更小,使用伪元素扩展点击区域:
css
.small-button::before {
content: "";
position: absolute;
inset: -8px;
}Z-Index Scale
Z-Index层级
Define a layered scale and never use arbitrary values:
css
--z-base: 0;
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 40;
--z-modal: 100;
--z-toast: 1000;定义分层的z-index比例,绝不要使用任意值:
css
--z-base: 0;
--z-dropdown: 10;
--z-sticky: 20;
--z-overlay: 40;
--z-modal: 100;
--z-toast: 1000;7. Motion & Interaction
7. 动效与交互
The Frequency-Based Decision Framework
基于使用频率的决策框架
This is the most important mental model for animation decisions:
| Frequency | Examples | Animation |
|---|---|---|
| 100+ times/day | Keyboard shortcuts, command palette actions, tab switches | None. Zero animation. Instant. |
| Tens of times/day | Hover effects, list item navigation, toggles | Remove or drastically reduce. 50-100ms max. |
| Occasional | Modals, drawers, toasts, page transitions | Standard animation. 150-300ms. |
| Rare / first-time | Onboarding, celebrations, empty states | Can add delight. 300-500ms, more elaborate. |
High-frequency animations feel sluggish. Low-frequency animations without motion feel jarring. Match the animation budget to usage frequency.
这是动效决策最重要的思维模型:
| 使用频率 | 示例 | 动效策略 |
|---|---|---|
| 每天100+次 | 键盘快捷键、命令面板操作、标签切换 | 无动效。零动画,即时响应。 |
| 每天数十次 | 悬停效果、列表项导航、开关 | 移除或大幅简化。最长50-100ms。 |
| 偶尔使用 | 模态框、抽屉、提示框、页面过渡 | 标准动效。150-300ms。 |
| 极少使用/首次使用 | 引导流程、庆祝动画、空状态 | 可添加趣味动效。300-500ms,更复杂的动画。 |
高频率动效会让用户感觉拖沓。低频率动效如果没有过渡,会显得突兀。根据使用频率分配动效预算。
Custom Easing Curves
自定义缓动曲线
Built-in CSS easings (, ) are too weak. Define custom curves:
easeease-in-outcss
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}内置CSS缓动效果(、)效果太弱。定义自定义曲线:
easeease-in-outcss
:root {
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
--ease-drawer: cubic-bezier(0.32, 0.72, 0, 1);
--ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
}Duration Guide
时长指南
| Element | Duration |
|---|---|
| Buttons, toggles | 100-160ms |
| Tooltips | 125-200ms |
| Dropdowns, popovers | 150-250ms |
| Modals, drawers | 200-500ms |
| Page transitions | 250-400ms |
UI animations should stay under 300ms. Never use for UI animations — it front-loads the pause and feels sluggish.
ease-in| 元素 | 时长 |
|---|---|
| 按钮、开关 | 100-160ms |
| 工具提示 | 125-200ms |
| 下拉菜单、弹出层 | 150-250ms |
| 模态框、抽屉 | 200-500ms |
| 页面过渡 | 250-400ms |
UI动效应控制在300ms以内。绝不要为UI动效使用——它会让停顿前置,显得拖沓。
ease-inEnter/Exit Asymmetry
入场/退场动效不对称
Exits should be softer and faster than enters. An enter animation at 250ms should have its exit at 150-200ms.
退场动效应比入场动效更柔和、更快。如果入场动效是250ms,退场动效应设置为150-200ms。
Split and Stagger Enter Animations
拆分与 stagger 入场动效
When multiple elements enter the viewport, stagger them by semantic chunks with ~50-100ms delay:
css
.stagger-item {
animation: fadeSlideIn 300ms var(--ease-out) both;
}
.stagger-item:nth-child(1) { animation-delay: 0ms; }
.stagger-item:nth-child(2) { animation-delay: 60ms; }
.stagger-item:nth-child(3) { animation-delay: 120ms; }当多个元素进入视口时,按语义分组设置约50-100ms的延迟:
css
.stagger-item {
animation: fadeSlideIn 300ms var(--ease-out) both;
}
.stagger-item:nth-child(1) { animation-delay: 0ms; }
.stagger-item:nth-child(2) { animation-delay: 60ms; }
.stagger-item:nth-child(3) { animation-delay: 120ms; }Scale Animations
缩放动画
Never animate from . Start from or higher, combined with opacity:
scale(0)scale(0.9)css
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}绝不要从开始动画。从或更高比例开始,结合透明度:
scale(0)scale(0.9)css
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.95); }
to { opacity: 1; transform: scale(1); }
}Press Feedback
按压反馈
Every pressable element should scale down slightly on :
:activecss
button:active {
transform: scale(0.97);
}所有可按压元素在状态下应略微缩小:
:activecss
button:active {
transform: scale(0.97);
}Interruptibility
可中断性
Use CSS transitions (not keyframe animations) for interactive state changes. Transitions can be interrupted mid-way; keyframes cannot. This matters for hover states, toggles, and any element the user might interact with rapidly.
使用CSS过渡(而非关键帧动画)处理交互状态变化。过渡可以在中途被中断;关键帧动画不行。这对悬停状态、开关以及用户可能快速交互的任何元素都很重要。
Popover Origin
弹出层原点
Make popovers transform-origin aware — they should grow from their trigger element, not from center. Exception: modals always originate from center.
弹出层应感知transform-origin——它们应从触发元素展开,而不是从中心展开。例外:模态框始终从中心展开。
Tooltip Hover Delay
工具提示悬停延迟
Skip the tooltip delay on subsequent hovers. If the user has already waited for one tooltip, show the next one immediately.
后续悬停时跳过工具提示延迟。如果用户已经等待过一次工具提示,下一次应立即显示。
Reduced Motion
减少动效
css
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}Respect . Reduce animations — don't eliminate opacity and color transitions entirely, as those provide important feedback.
prefers-reduced-motioncss
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
transition-duration: 0.01ms !important;
}
}尊重设置。减少动效——不要完全移除透明度和颜色过渡,因为它们提供重要的反馈。
prefers-reduced-motionHover Gate
悬停判断
Gate hover animations behind a media query so touch devices don't trigger stuck hover states:
css
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-2px); }
}Referencefor deep dives on spring physics, gesture-driven animation, and complex choreography.references/animation-playbook.md
通过媒体查询控制悬停动效,避免触摸设备触发卡住的悬停状态:
css
@media (hover: hover) and (pointer: fine) {
.card:hover { transform: translateY(-2px); }
}如需深入了解弹簧物理、手势驱动动画和复杂编排,请参考。references/animation-playbook.md
8. Component Craft
8. 组件设计
Primitives
基础组件
Use Radix UI primitives for accessible, unstyled foundations. Use CVA (class-variance-authority) for type-safe component variants:
tsx
import { cva } from "class-variance-authority";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground",
},
size: {
sm: "h-9 px-3 text-sm",
default: "h-10 px-4 py-2",
lg: "h-11 px-8 text-lg",
},
},
defaultVariants: { variant: "default", size: "default" },
}
);使用Radix UI基础组件作为无障碍、无样式的基础。使用CVA(class-variance-authority)实现类型安全的组件变体:
tsx
import { cva } from "class-variance-authority";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-2",
{
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90",
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
outline: "border border-input hover:bg-accent hover:text-accent-foreground",
ghost: "hover:bg-accent hover:text-accent-foreground",
},
size: {
sm: "h-9 px-3 text-sm",
default: "h-10 px-4 py-2",
lg: "h-11 px-8 text-lg",
},
},
defaultVariants: { variant: "default", size: "default" },
}
);Button
按钮组件
- Scale on press (on
transform: scale(0.97)):active - Visible focus ring (never without replacement)
outline: none - Loading state with spinner replacing label, maintaining button dimensions
- Disabled state at with
opacity: 0.5pointer-events: none
- 按压时缩放(状态下
:active)transform: scale(0.97) - 可见的焦点环(绝不要使用而不提供替代方案)
outline: none - 加载状态用 spinner 替换标签,保持按钮尺寸不变
- 禁用状态设置并添加
opacity: 0.5pointer-events: none
Card
卡片组件
- Concentric border radius between card and inner elements
- Layered shadows (not borders) for depth
- Hover state: subtle elevation change (+ shadow increase)
translateY(-1px)
- 卡片与内部元素使用同心圆角
- 用分层阴影(而非边框)实现深度
- 悬停状态:轻微提升(+ 阴影增强)
translateY(-1px)
Dialog / Modal
对话框/模态框
- Focus trap (keyboard cannot escape to elements behind)
- ESC to close, click outside overlay to close
- , fade + scale enter animation
transform-origin: center - ,
aria-modal="true",role="dialog"aria-labelledby
- 焦点陷阱(键盘无法聚焦到模态框后方的元素)
- 按ESC关闭,点击遮罩层关闭
- ,淡入+缩放入场动画
transform-origin: center - 设置、
aria-modal="true"、role="dialog"aria-labelledby
Form
表单组件
- Visible labels always — never placeholder-only inputs
- Error messages near the field with for screen readers
aria-live="polite" - Progressive disclosure: show advanced fields only when needed
- Use React Hook Form + Zod for validation
- 始终显示可见标签——绝不要仅使用占位符作为输入框标签
- 错误消息靠近输入框,并设置供屏幕阅读器读取
aria-live="polite" - 渐进式披露:仅在需要时显示高级字段
- 使用React Hook Form + Zod进行验证
Theming
主题化
Use shadcn CSS variable pattern (HSL format) for all component colors. Wrap client-interactive components in server components for Next.js App Router compatibility.
Referencefor the full component catalog with copy-paste implementations.references/component-patterns.md
使用shadcn的CSS变量模式(HSL格式)定义所有组件颜色。在Next.js App Router中,将客户端交互组件包裹在服务器组件中以保证兼容性。
如需完整的组件目录及可复制粘贴的实现代码,请参考。references/component-patterns.md
9. Accessibility Essentials
9. 无障碍设计要点
Semantic HTML First
优先使用语义化HTML
Use , , , , , , before reaching for ARIA. A gives you keyboard handling, focus management, and screen reader semantics for free. A gives you none of that.
<button><nav><main><header><footer><article><section><button><div onClick>在使用ARIA之前,优先使用、、、、、、等标签。会免费提供键盘处理、焦点管理和屏幕阅读器语义。而则没有这些功能。
<button><nav><main><header><footer><article><section><button><div onClick>Keyboard Navigation
键盘导航
- Tab / Shift+Tab: move between focusable elements
- Enter / Space: activate buttons and links
- Arrow keys: navigate within lists, menus, tabs, radio groups
- Escape: close modals, popovers, dropdowns
- Home / End: jump to first/last item in lists
- Tab / Shift+Tab:在可聚焦元素之间切换
- Enter / Space:激活按钮和链接
- 方向键:在列表、菜单、标签页、单选组内导航
- Escape:关闭模态框、弹出层、下拉菜单
- Home / End:跳转到列表的第一个/最后一个项
Focus Management
焦点管理
- Visible focus rings on all interactive elements — NEVER use without a replacement
outline: none - Trap focus inside modals (Tab wraps within the modal, not behind it)
- Restore focus to the trigger element when a modal/popover closes
- Use to show rings only for keyboard users, not mouse clicks:
focus-visible
css
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}- 所有交互元素都要有可见的焦点环——绝不要使用而不提供替代方案
outline: none - 模态框内要捕获焦点(Tab键在模态框内循环,不会聚焦到后方元素)
- 模态框/弹出层关闭后,将焦点恢复到触发元素
- 使用仅在键盘用户操作时显示焦点环,鼠标点击时不显示:
focus-visible
css
:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}ARIA Attributes
ARIA属性
- for icon-only buttons:
aria-label<button aria-label="Close menu">X</button> - to associate headings with sections
aria-labelledby - to link help text or error messages to inputs
aria-describedby - for dynamic content updates (toast messages, form errors)
aria-live="polite" - for decorative elements (icons next to text labels)
aria-hidden="true" - for toggleable elements (dropdowns, accordions)
aria-expanded
- 纯图标按钮使用:
aria-label<button aria-label="Close menu">X</button> - 使用将标题与章节关联
aria-labelledby - 使用将帮助文本或错误消息与输入框关联
aria-describedby - 动态内容更新(提示框、表单错误)使用
aria-live="polite" - 装饰性元素(文本标签旁的图标)使用
aria-hidden="true" - 可切换元素(下拉菜单、手风琴)使用
aria-expanded
Color and Contrast
色彩与对比度
- WCAG AA: 4.5:1 for normal text, 3:1 for large text
- Never use color as the sole indicator — pair with icons, text, or patterns
- Test in both light and dark modes
- WCAG AA标准:普通文本4.5:1,大文本3:1
- 绝不要仅使用颜色作为唯一标识——搭配图标、文本或图案
- 在明暗模式下分别测试
Images and Media
图片与媒体
- Descriptive text for meaningful images:
altalt="Dashboard showing 23% revenue growth" - Empty for purely decorative images
alt="" - Captions for video, transcripts for audio
- 有意义的图片使用描述性文本:
altalt="显示收入增长23%的仪表盘" - 纯装饰性图片使用空
alt="" - 视频添加字幕,音频提供文字转录
Navigation Aids
导航辅助
- Skip link: first focusable element, hidden until focused:
html
<a href="#main-content" class="sr-only focus:not-sr-only">
Skip to main content
</a>- Heading hierarchy: sequential h1 through h6, no level skips. One per page.
<h1>
- 跳转链接:第一个可聚焦元素,默认隐藏,聚焦时显示:
html
<a href="#main-content" class="sr-only focus:not-sr-only">
跳转到主要内容
</a>- 标题层级:按顺序使用h1到h6,不要跳过层级。每页一个。
<h1>
Touch Targets
触摸目标
- Minimum 44x44px interactive area
- 8px minimum spacing between adjacent touch targets
- Extend small visual elements with invisible padding or pseudo-elements
- 最小触摸区域44x44px
- 相邻触摸目标之间最小间距8px
- 使用不可见的内边距或伪元素扩展小视觉元素的触摸区域
Testing
测试
- Automated: axe-core in CI, Lighthouse accessibility score 90+
- Manual: full keyboard-only navigation test
- Screen reader: test with VoiceOver (macOS) or NVDA (Windows)
- Visual: zoom to 200%, check nothing breaks or overlaps
Referencefor the full audit guide with pass/fail criteria.references/accessibility-checklist.md
- 自动化测试:CI中使用axe-core,Lighthouse无障碍评分90+
- 手动测试:完整的纯键盘导航测试
- 屏幕阅读器测试:使用VoiceOver(macOS)或NVDA(Windows)测试
- 视觉测试:放大到200%,检查是否有元素损坏或重叠
如需完整的审核指南及通过/失败标准,请参考。references/accessibility-checklist.md
10. Pre-Delivery Review
10. 交付前检查
Run through this checklist before considering any UI implementation complete:
在认为UI实现完成之前,请完成以下检查清单:
Typography
排版
- Font smoothing applied ()
-webkit-font-smoothing: antialiased - Headings use
text-wrap: balance - Dynamic numbers use
font-variant-numeric: tabular-nums
- 已应用字体平滑()
-webkit-font-smoothing: antialiased - 标题使用
text-wrap: balance - 动态数字使用
font-variant-numeric: tabular-nums
Color
色彩
- All colors referenced via semantic tokens, no hardcoded hex in components
- Color contrast meets WCAG AA (4.5:1 normal text, 3:1 large text)
- Dark mode tested separately for contrast
- 所有颜色通过语义化令牌引用,组件中无硬编码十六进制值
- 色彩对比度符合WCAG AA标准(普通文本4.5:1,大文本3:1)
- 已单独测试深色模式的对比度
Spatial
空间设计
- Nested rounded elements use concentric border radius
- Spacing follows 4px / 8px scale consistently
- Interactive elements have 44x44px minimum hit area
- Shadows used instead of borders where appropriate
- 嵌套圆角元素使用同心圆角
- 间距一致遵循4px/8px比例
- 交互元素的最小点击区域为44x44px
- 合适的场景下使用阴影替代边框
Motion
动效
- Animation frequency matches usage frequency (no animation on high-frequency actions)
- No anywhere — specific properties only
transition: all - Enter animations split and staggered where multiple elements appear
- respected
prefers-reduced-motion
- 动画频率与使用频率匹配(高频率操作无动画)
- 无——仅指定具体属性
transition: all - 多个元素入场时使用拆分与stagger动画
- 已尊重设置
prefers-reduced-motion
Accessibility
无障碍设计
- All interactive elements keyboard accessible
- Focus rings visible on keyboard navigation (never without replacement)
outline: none - Semantic HTML used before ARIA
- on dynamic content updates
aria-live
Referencefor the extended 30-item checklist with severity ratings and automated testing commands.references/review-checklist.md
- 所有交互元素可通过键盘访问
- 键盘导航时焦点环可见(绝不要使用而不提供替代方案)
outline: none - 优先使用语义化HTML而非ARIA
- 动态内容更新已设置
aria-live
如需包含30项内容的扩展检查清单、严重程度评级及自动化测试命令,请参考。references/review-checklist.md