interface-kit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Interface 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's
references/
directory.

如果项目根目录存在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.
PriorityLevelWhat It Means
AccessibilityCRITICALContrast 4.5:1, keyboard nav, ARIA semantics, visible focus rings. Ship nothing that excludes users.
PerformanceHIGHWebP/AVIF images, lazy loading below fold, CLS < 0.1, transform-only animations on the compositor thread.
TypographyHIGHFont smoothing, text-wrap balance/pretty, tabular-nums for data, 65ch max line length.
Layout & SpatialHIGH4/8px grid, concentric border radius, optical alignment over geometric.
Color & ThemeMEDIUMHSL custom properties, semantic tokens, dark mode pairs tested separately.
Motion & InteractionMEDIUMFrequency-based animation decisions, 150-300ms durations, ease-out default.
Polish & DetailsLOWLayered 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 (
filter: url(#noise)
), layered transparencies, subtle background patterns, duotone image treatments.
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;
}
balance
distributes heading lines evenly.
pretty
avoids orphaned words in body text.
css
h1, h2, h3, h4, h5, h6 {
  text-wrap: balance;
}

p, li, dd, blockquote {
  text-wrap: pretty;
}
balance
会让标题行分布均匀。
pretty
会避免正文出现孤立单词。

Numeric Display

数字显示

css
.data-value, .price, .counter, [data-numeric] {
  font-variant-numeric: tabular-nums;
}
Use
tabular-nums
for any number that updates dynamically — prices, counters, table columns. Without it, layout shifts as digit widths change.
css
.data-value, .price, .counter, [data-numeric] {
  font-variant-numeric: tabular-nums;
}
对于任何动态更新的数字——价格、计数器、表格列——使用
tabular-nums
。如果不使用,数字宽度变化时会导致布局偏移。

Scale 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:
    max-width: 65ch
    for body text. Long lines destroy readability.
  • 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
font-weight
for hierarchy within a family:
  • 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 (
#000
). Text goes light but not pure white (
#fff
). Test contrast separately for dark mode — what passes in light may fail in dark.
css
.dark {
  --background: 222.2 84% 4.9%;
  --foreground: 210 40% 98%;
  /* ... 降低饱和度的浅色调变体——不是简单反转颜色 */
}
深色模式不是“反转颜色”。使用降低饱和度的浅色调变体。背景色要深但不是纯黑(
#000
)。文本要浅但不是纯白(
#fff
)。单独测试深色模式的对比度——在浅色模式下通过的对比度,在深色模式下可能不达标。

Contrast 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 + padding
css
/* 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 + padding
css
/* 正确:同心圆角 */
.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
box-shadow
values for natural depth instead of using borders:
css
.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-shadow
值实现自然的层次感,而不是使用边框:
css
.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 / 128

Hit 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:
FrequencyExamplesAnimation
100+ times/dayKeyboard shortcuts, command palette actions, tab switchesNone. Zero animation. Instant.
Tens of times/dayHover effects, list item navigation, togglesRemove or drastically reduce. 50-100ms max.
OccasionalModals, drawers, toasts, page transitionsStandard animation. 150-300ms.
Rare / first-timeOnboarding, celebrations, empty statesCan 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 (
ease
,
ease-in-out
) are too weak. Define custom curves:
css
: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缓动效果(
ease
ease-in-out
)效果太弱。定义自定义曲线:
css
: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

时长指南

ElementDuration
Buttons, toggles100-160ms
Tooltips125-200ms
Dropdowns, popovers150-250ms
Modals, drawers200-500ms
Page transitions250-400ms
UI animations should stay under 300ms. Never use
ease-in
for UI animations — it front-loads the pause and feels sluggish.
元素时长
按钮、开关100-160ms
工具提示125-200ms
下拉菜单、弹出层150-250ms
模态框、抽屉200-500ms
页面过渡250-400ms
UI动效应控制在300ms以内。绝不要为UI动效使用
ease-in
——它会让停顿前置,显得拖沓。

Enter/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
scale(0)
. Start from
scale(0.9)
or higher, combined with opacity:
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
:active
:
css
button:active {
  transform: scale(0.97);
}
所有可按压元素在
:active
状态下应略微缩小:
css
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
prefers-reduced-motion
. Reduce animations — don't eliminate opacity and color transitions entirely, as those provide important feedback.
css
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
尊重
prefers-reduced-motion
设置。减少动效——不要完全移除透明度和颜色过渡,因为它们提供重要的反馈。

Hover 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); }
}
Reference
references/animation-playbook.md
for deep dives on spring physics, gesture-driven animation, and complex choreography.

通过媒体查询控制悬停动效,避免触摸设备触发卡住的悬停状态:
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 (
    transform: scale(0.97)
    on
    :active
    )
  • Visible focus ring (never
    outline: none
    without replacement)
  • Loading state with spinner replacing label, maintaining button dimensions
  • Disabled state at
    opacity: 0.5
    with
    pointer-events: none
  • 按压时缩放(
    :active
    状态下
    transform: scale(0.97)
  • 可见的焦点环(绝不要使用
    outline: none
    而不提供替代方案)
  • 加载状态用 spinner 替换标签,保持按钮尺寸不变
  • 禁用状态设置
    opacity: 0.5
    并添加
    pointer-events: none

Card

卡片组件

  • Concentric border radius between card and inner elements
  • Layered shadows (not borders) for depth
  • Hover state: subtle elevation change (
    translateY(-1px)
    + shadow increase)
  • 卡片与内部元素使用同心圆角
  • 用分层阴影(而非边框)实现深度
  • 悬停状态:轻微提升(
    translateY(-1px)
    + 阴影增强)

Dialog / Modal

对话框/模态框

  • Focus trap (keyboard cannot escape to elements behind)
  • ESC to close, click outside overlay to close
  • transform-origin: center
    , fade + scale enter animation
  • 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
    aria-live="polite"
    for screen readers
  • 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.
Reference
references/component-patterns.md
for the full component catalog with copy-paste implementations.

使用shadcn的CSS变量模式(HSL格式)定义所有组件颜色。在Next.js App Router中,将客户端交互组件包裹在服务器组件中以保证兼容性。
如需完整的组件目录及可复制粘贴的实现代码,请参考
references/component-patterns.md

9. Accessibility Essentials

9. 无障碍设计要点

Semantic HTML First

优先使用语义化HTML

Use
<button>
,
<nav>
,
<main>
,
<header>
,
<footer>
,
<article>
,
<section>
before reaching for ARIA. A
<button>
gives you keyboard handling, focus management, and screen reader semantics for free. A
<div onClick>
gives you none of that.
在使用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
    outline: none
    without a replacement
  • Trap focus inside modals (Tab wraps within the modal, not behind it)
  • Restore focus to the trigger element when a modal/popover closes
  • Use
    focus-visible
    to show rings only for keyboard users, not mouse clicks:
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属性

  • aria-label
    for icon-only buttons:
    <button aria-label="Close menu">X</button>
  • aria-labelledby
    to associate headings with sections
  • aria-describedby
    to link help text or error messages to inputs
  • aria-live="polite"
    for dynamic content updates (toast messages, form errors)
  • aria-hidden="true"
    for decorative elements (icons next to text labels)
  • aria-expanded
    for toggleable elements (dropdowns, accordions)
  • 纯图标按钮使用
    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
    alt
    text for meaningful images:
    alt="Dashboard showing 23% revenue growth"
  • Empty
    alt=""
    for purely decorative images
  • Captions for video, transcripts for audio
  • 有意义的图片使用描述性
    alt
    文本:
    alt="显示收入增长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
    <h1>
    per page.
  • 跳转链接:第一个可聚焦元素,默认隐藏,聚焦时显示:
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
Reference
references/accessibility-checklist.md
for the full audit guide with pass/fail criteria.

  • 自动化测试: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
    transition: all
    anywhere — specific properties only
  • Enter animations split and staggered where multiple elements appear
  • prefers-reduced-motion
    respected
  • 动画频率与使用频率匹配(高频率操作无动画)
  • transition: all
    ——仅指定具体属性
  • 多个元素入场时使用拆分与stagger动画
  • 已尊重
    prefers-reduced-motion
    设置

Accessibility

无障碍设计

  • All interactive elements keyboard accessible
  • Focus rings visible on keyboard navigation (never
    outline: none
    without replacement)
  • Semantic HTML used before ARIA
  • aria-live
    on dynamic content updates
Reference
references/review-checklist.md
for the extended 30-item checklist with severity ratings and automated testing commands.
  • 所有交互元素可通过键盘访问
  • 键盘导航时焦点环可见(绝不要使用
    outline: none
    而不提供替代方案)
  • 优先使用语义化HTML而非ARIA
  • 动态内容更新已设置
    aria-live
如需包含30项内容的扩展检查清单、严重程度评级及自动化测试命令,请参考
references/review-checklist.md