---
name: ui-craft
description: 新建、重设计、打磨或审查界面（页面、组件、弹层、落地页）时读，也用于单项的动效、配色、排版、图标、表单反馈、无障碍与移动端适配
---

# UI Craft

项目已有组件、token、lint、DESIGN.md 和平台规范时以它们为准；本文件补它们表达不了的品味和默认取值。

## 开工

1. 读现有 Button、Input、菜单、Dialog、token 和一个相邻页面，全局尺寸沿用项目值。改已有界面时，先 grep 列出同类组件（Tab、Toast、弹层、行菜单、头像、图注、Radio）的全部实例，改在共享实现上，不逐处补。
2. 定主要输入（`pointer`、`touch`、`hybrid`）和一个默认密度（`compact`、`comfortable`、`touch`）；组件因业务例外时用语义变体承载。窗口变宽时增加内容、列或面板，控件尺寸固定。原生桌面应用用系统控件尺寸，下表供 Web、Electron 和自绘界面。
3. 新建或大改时，先从请求、README 和代码定主要用户与核心任务；每页一个主要任务，定好层级与焦点再选 Card、分栏、侧栏或长页结构。没有既有品牌时选一个明确视觉方向，直接落到配色、字体、间距和表面层级。

## 动手前按情形读参考

任务涉及左列情形时，写代码前先读右列文件；动效取值、表单与反馈规则、图标描边都在参考里，本文件只有总则。

| 情形 | 读取 |
|---|---|
| 动效、转场、进出场、手风琴、Tab 指示条、弹簧 | `reference/motion.md` |
| 拖拽、swipe、bottom sheet、carousel | `reference/gestures.md` |
| 选图标、描边、品牌 logo、图标动效 | `reference/icons.md` |
| 表单、设置开关、Label/Placeholder、校验、提交状态、Toast/Banner/Tooltip | `reference/forms-and-feedback.md` |
| 删重复页眉、描述、helper、重复 CTA | `reference/content-reduction.md` |
| 字体、字阶、行高、换行截断、混合方向 | `reference/typography.md` |
| 调色板、语义色、对比度、暗色与高对比 | `reference/color.md` |
| 焦点、键盘、读屏播报、命中区、禁用态、缩放重排 | `reference/accessibility.md` |
| 手机上像网页：hover 粘住、100vh、输入放大、安全区、状态栏颜色 | `reference/mobile.md` |
| 审查界面并出报告 | `reference/review.md` |

## 品味

好看现代 = 克制的骨架 + 一个有分量的焦点 + 到位的细节。每屏只有一个视觉焦点，由真实内容或真实交互充当（数据、预览、作品、主输入），字号、体积、彩度和最用心的动效都给它；导航、控件、列表保持扁平克制。减法只删骨架上的噪音，不删焦点与信息。界面显得素、空、普通时，先加强排版层级、换上真实内容、把焦点做足，不加装饰、标签或卡片。焦点需要特效或成品动效件时，按 ui-picks 选库移植。

营销页首屏先让人看懂产品是什么、怎么开始：产品名、一句主张、主行动（下载、安装、试用）和真实产品视觉最醒目，次要卖点后移或收小。缺素材时用 gpt-image 生成产品相关的图，或按 ui-picks 取现成件，不留占位图，也不用文字和卡片凑数。

### 标签与页眉

以下是生成界面最常见的噪音，默认都不加：

- 标题上方的小号大写标签（eyebrow / kicker）。
- 给每节或每张卡加的分类、编号、状态小标签与徽标（01/02/03、「推荐」「NEW」）。
- 页面顶部重复导航当前项的页眉与副标题；Tab 列表常驻可见时，panel 里重复 tab 名的标题。
- 标题、分区、弹层、设置项下面的说明句。机制解释、候选来源、玩法等教学说明收进标签旁的问号 Toggletip；操作前必须知道的范围、门槛、后果直写并持久可见。

标题直接说内容，层级靠字号、字重和间距。标签只在承载用户需要区分的真实状态时出现（未读、失败、已过期）。导航在当前断点被隐藏、页面可经深链独立打开或页面很长时，才显示一个简短标题；省掉可见标题的内容区用 `aria-labelledby` 或准确的 accessible name 保持可定位，文档 `<title>` 随视图更新。

### 其他模板痕迹

- 渐变文字、标题里的斜体强调词、等宽字体的小标签、奶油色或米黄色背景、默认玻璃拟态、无限等尺寸 Card Grid、无业务依据的大数字 Hero。
- 卡片套卡片、渐变底加内环线、卡片左侧或顶部的彩色条（有提示语义的 Callout、Alert 除外，颜色走共享语义 token）、弹层顶部的彩线。
- 分割线：弹层、卡片、侧栏、菜单、表单段落的头尾与内容之间，文件、会话、成员这类列表行之间，一律用间距、对齐、hover 底色或轻微底色差分组；只有多列对比的数据表需要行线。确需分隔时用项目里统一的一种虚线或发丝线组件，不手写 border。
- 图标外套的底色方块、圆圈或描边。图标裸放，要分类色就给图标本身着色。
- 状态胶囊（带底色的圆角小标签）、每种状态各配一层彩色底、进行中用绿色。状态由图标与状态词的颜色表达；底色只留给要用户处理的一两种，满屏都上色就不再表示「要你看」；绿色读作完成，进行中用蓝或中性色。
- 同类条目各有各的行数（有的多一行读数、有的没有），时间混写分钟、钟点、秒表。同类条目固定行数与列位，缺的那一格留空；时间只用一种写法。
- 鼠标点击后留下的外圈方框：按钮、卡片、勾选只在键盘聚焦时出环（`:focus-visible`），文本框聚焦只加深边框色。

目标写法：用间距和对齐分组，最用心的动效集中给焦点。去掉一种痕迹后检查有没有换成近亲（分割线变 1px 底边、彩条变彩色左边框、说明句变灰色小字），换了等于没去。

## 密度与控件尺寸

项目没有设计系统时的默认值，平台规范优先：

| Profile | 典型场景 | Button / Input | Icon button | Row | Label | Icon | 水平 padding |
|---|---|---:|---:|---:|---:|---:|---:|
| `compact` | 浏览器插件、桌面工具栏、数据密集工具 | 32px | 28–32px | 28–32px | 13px | 14–16px | 10–12px |
| `comfortable` | 普通桌面应用、设置页、Dialog | 36px | 32–36px | 36–40px | 14px | 16–18px | 12–16px |
| `touch` | 触屏或触控为主的混合设备 | 44px；Material 48dp | 44/48px | 44/48px | 14–16px | 18–20px | 16–20px |

- 紧凑桌面的常用操作不低于 28px；触屏命中区只给 `touch` profile，可见图形可以更小，扩展命中区互不重叠。
- Button、Input、Select 和相邻分段控件同高；图标按钮正方形；含图标按钮与纯文字按钮同高，文字与图标间距 6–8px。主 CTA 靠颜色、位置和层级突出，不靠加高。
- 密度由一套 token 或 variant 控制（`control-height`、`control-padding-x`、`icon-size`），全部组件共用。
- 同心圆角：`outer radius = inner radius + padding`；两层间距超过 24px 时视为独立表面，各自取值。

## 排版与间距

| 用途 | `compact` | `comfortable` |
|---|---:|---:|
| 正文 | 13.5–14px | 14–15px |
| 控件、菜单、条目标题 | 13px | 14px |
| 次要说明 | 12–13px | 12.5–13.5px |
| 非关键元信息 | 11.5–12px | 12px |

- 关键标签、状态和操作文字不小于 12px；控件嫌大时缩控件，字号不动。
- 次要文字靠颜色降级，不靠细字重。CJK 小字号用更高行高并实机看。
- 4px 间距尺度；2、6、10px 只用于图标或光学校准。相关内容紧，分组之间松。
- 选字体、字阶、行高字距、换行截断与混合方向见 `reference/typography.md`。

## 图标

- Tab、分类、设置节标题、导航项、状态词配图标，让用户靠图形扫读；次要和行内操作（更多、删除、返回、停止、语言、复制）用 icon-only 按钮，配 accessible name 和 tooltip，文字按钮留给主操作与需要说清后果的确认。
- 功能图标单色（`currentColor`），颜色只表达状态或分类；品牌、平台、第三方产品名用官方 SVG，不手画。
- 图标不细不小：16px 槽位描边取 2，尺寸跟随相邻文字。细节见 `reference/icons.md`。

## 视觉层级

- Card 只包裹真正独立、可操作的对象，边界用中性色。去掉 border、阴影、背景、圆角后理解和操作不受影响的，就不该是 Card：设置组、表单段落、统计行、说明内容靠标题和间距分组，不上卡。
- Tab 与分段控件：槽底加浮起的选中块，选中块在选项间滑动；全项目同一个实现。
- 浮层、可拖拽卡片这类"可抬起"的表面用 1px 半透明 ring 加柔阴影（`0 0 0 1px oklch(0 0 0 / .06), 0 4px 12px -2px oklch(0 0 0 / .08)`，暗色改单层 `0 0 0 1px oklch(1 0 0 / .08)`）；静态内容卡不加阴影。`forced-colors: active` 会清掉 `box-shadow`，靠阴影表达边界的表面在该媒体查询里补 `border: 1px solid`。分割线、表格边界、输入框轮廓、选中态和 focus ring 保持真实 border。
- 图片需要边界时加 1px 纯中性描边（亮色 `oklch(0 0 0 / .1)`，暗色 `oklch(1 0 0 / .1)`）；带色相的近黑叠在图片边缘像脏污。
- 弹层的关闭按钮与标题同一行（无标题时贴角），不单占一行空白；弹层尺寸随内容取，不撑满。
- 可滚动或折叠区域给出可见提示：露出下一项的一部分、边缘渐隐或计数。内部滚动区用 `scrollbar-width: thin` 和 `scrollbar-gutter: stable`，不用默认的粗滚动条。
- Sticky 操作只给高频、跨长列表仍需可见的动作，并让出内容、键盘焦点和小窗口视口。

## 空态与渐进披露

- 容器为空时，只对已有内容才有意义的控件（搜索、筛选、排序、计数、批量操作、依赖既有内容的次级入口）等内容出现后再渲染，位置与最终布局一致。整屏让给一个居中引导：一句状态 + 一句下一步 + 1（最多 2）个此刻就能完成的动作；此刻走不通的能力写成一句预告。
- 加载中留白，数据到达再决定空态或内容。失败态与空态分开，失败可重试。
- 空态文案说清"还没有"与"怎么开始"，用中性色和常规图标。插画先用产品已有品牌图形；确需生成时按产品语气（gpt-image），统一光影与配色。呼吸、漂浮动效只在语气支持时用。
- 有合理缺省值的可选字段收进「添加 X（可选）」显式展开，展开后保持展开：双向折叠会把已填但非法的值藏起来。数量区间、格式要求等硬约束以紧凑形式常驻。
- 低频可选输入默认收成 icon-only 或一行入口，点开出输入框（autoFocus），失焦且为空时收回；有内容时保持展开。必填项常驻。placeholder 或禁用态提示已承担"下一步"时，空内容区留白。

## 文案

- 描述、提示、占位、Toast、按钮文案单句结尾不加句号。
- Button 与链接写具体动作或目的，脱离相邻正文仍能理解；上下文已唯一确定对象时省略对象名。
- 设置项名称写"打开后会发生什么"，用肯定句；描述默认不写，需要时按「标签与页眉」收进问号。分区标题用平实名词，破坏性操作放在常规分区里用红色按钮，不起"危险区"这类标题。
- 中英文案保持语义、阈值和数量一致；只有措辞本身是需求时才用测试锁定。
- 界面不显示内部 ID、订单号原串、枚举名和错误码；要给用户留痕时收进「详情」或复制按钮，错误写成原因加下一步。

## 交互

- 每个交互组件实现适用的 default、hover、focus-visible、active、disabled、loading、error、success 状态。Web 自定义控件写 `cursor: pointer`（Tailwind v4 preflight 把 button 设回 `default`）；原生桌面控件遵循平台行为。
- 上传、删除、保存、发送点下去的瞬间进入进行中（行内 spinner 或进度，批量时按条目），成功短暂着绿后回常态，失败行内标红并可重试。不让用户对着空白等结果。
- 会变的数字、状态词和按钮文案，容器按最大形态预留尺寸（`tabular-nums`、固定宽或 `min-height`），变化不推动邻居；骨架与最终内容同尺寸。
- 点击当前 tab、当前选项等幂等目标，视图保持原样。
- 有选中项的列表打开时让当前项进入可视区，用 `aria-current`、`aria-selected` 表达状态。
- Chat、日志、时间线打开时跟随最新内容；用户离开底部后暂停，回到底部恢复。阈值由行高或 token 决定，用事件和 observer 驱动。
- 复制按钮只在复制是高频任务时常驻；否则在 hover、focus-within 或上下文菜单中出现，键盘可达。

## 动效

- 预算按触发频率分档：键盘驱动的重复操作（命令面板开合、快捷键、筛选重排）即时；容器进出（弹层、抽屉、Tab 面板、列表进详情、新增或删除的行）和选中指示的移动是常规操作，都有短进出；庆祝、重绘图标、成品动效件只给低频或首次体验。同一类容器全项目走同一套进出配方，不出现"旧会话有动效、新建没有"。
- 每个动效说得出用途：反馈、空间连续、状态变化、避免跳变、讲解。高频处"好看"不算用途。
- 方向表达空间关系：同级切换（Tab、分段）沿水平轴，方向跟随选项先后；进入详情向前、返回反向；浮层从触发点或边缘长出。
- 位移、缩放和进出场只动 `transform`/`opacity`；可被快速重复触发的用 transition 或 spring（从当前值中断重定向），不用 keyframes（中断即从零重播）。
- 反馈 120–180ms，UI 动效不超过 300ms（整屏 Drawer、Sheet 至多 500ms）；标志性动效 280–700ms，只出现在少数低频、高意图组件。

## 压测与完成标准

压测：用真实最坏数据，从数据入口替换而不改组件；定宽容器配 `min-width: 0` 和明确的换行或截断策略，截断后原文仍可获取：长名（`Aleksandra Wiśniewska-Kowalczyk`）、无空格长邮箱、单字名（`Jo`）、缺失的可选字段与头像、计数 0 / 1 / 1284、超长译文（德语复合词）、CJK、RTL、emoji 开头的名字、1000+ 行列表；在真实容器宽、320px、200% 缩放和暗色下看。常见签名：头像被挤成椭圆 → `flex-shrink: 0`；文字撑破容器 → 文本列 `min-width: 0`（grid 用 `minmax(0, 1fr)`）；邮箱、URL 溢出 → `overflow-wrap: anywhere`；"1 members" → `Intl.PluralRules`；裸数字 → `Intl.NumberFormat`；文件名、路径、哈希末尾才有区别 → 中间截断；金额、日期等要比较的值不截断。

完成标准，逐项核对本次改动触及的屏、组件与交互：
- 每屏的焦点已指认并做足。
- 「标签与页眉」「其他模板痕迹」已逐项对照目标界面。
- 同类组件的全部实例已列出并走同一个实现。
- 每个异步操作都看过进行中、成功、失败三态；每个渲染出的值都试过最坏值。
- 截图逐行看过：同一行的图标、文字、徽标、头像、右侧操作组沿交叉轴居中对齐。
- 密度 profile 落在 token 或共享组件上，而非逐处覆写。
- 动效已录屏或逐帧看过起点、终点、中途反向和 reduced-motion。
- 点击、切页、弹层与侧栏开合已用平台工具在真实数据量下测过响应：下一帧就有变化，过程中主线程没有超过一帧的长任务。截图和录屏看不出卡顿，方法见 `reference/motion.md`「检查动效」。
- 网页界面跑过 `bbu a11y <url>`（axe 无障碍审计），serious 与 critical 违规已修，修在颜色 token 或共享组件上。
