---
name: form-motion
description: "FORM UI 动效词典：10 个克制、跟手、可访问的界面微交互，每个都配原始提示词、可改项、验收标准和自动验收脚本——连续形变按钮、液体标签指示器、弹性滑块、柔性开关、原位展开卡片、层叠通知、命令面板、拖动排序、跟随提示、自绘折线图。共用一个从当前位置和速度重定向的阻尼弹簧。当用户说「按钮自己变成加载和完成」「选中条像软糖追过去」「拖到头还能拽一点」「开关圆点拉长」「卡片原位展开」「通知层叠」「Cmd+K 命令面板」「拖动排序」「提示跟随鼠标」「折线自己画出来」，或点名 FORM 动效库、要把某个样例用到自己的页面时使用。只在明确请求时触发，忽略顺带提及。"
---

# FORM 动效词典

10 个可操作的界面动效，每个都由一段提示词定义，并配有可以自动跑的验收。用法是先挑出这次需要的样例，然后只读它那一节，照着提示词实现到用户的页面或组件里，最后跑验收。

## 选样例

| ID | 用户可能会说 | 样例 |
|---|---|---|
| 01 | 按钮自己变成加载和完成 | 连续形变按钮 |
| 02 | 选中条像软糖一样追过去 | 液体标签指示器 |
| 03 | 拖到头还能拽一点 | 弹性音量滑块 |
| 04 | 开关的圆点移动时稍微拉长 | 柔性开关 |
| 05 | 这张卡自己长出更多内容 | 原位展开卡片 |
| 06 | 新通知压在前面，旧的往后退 | 层叠通知 |
| 07 | 打开就能输入搜索并回车 | 搜索命令面板 |
| 08 | 抓住一行，其他行自然让位 | 跟手拖动排序 |
| 09 | 提示跟随鼠标但不挡住它 | 跟随式提示 |
| 10 | 折线自己画出来，悬停解释数据 | 自绘折线图 |

一次只取需要的样例，不要把整个词典塞进上下文。

## 文件

- [`references/samples.md`](references/samples.md)：每个样例一节，包括提示词原文、适用场景、可改项、验收标准和测试钩子。
- [`assets/motion.js`](assets/motion.js)：共用弹簧 `FormMotion.Motion`，无依赖。
- [`assets/reference.html`](assets/reference.html)：原作的离线目录页，含 10 个参考实现（`mount01`…`mount10`）。`?sample=NN` 打开对应样例。
- [`scripts/verify.mjs`](scripts/verify.mjs)：用真实的指针和键盘操作逐条验收。另外查减少动态效果、390 宽手机有没有横向溢出、页面有没有报错。
- `references/catalog.json`：结构化原始数据。`scripts/build_samples_md.py` 用它重新生成 samples.md。

## 步骤

1. **定样例和替换项**：把用户的话对到上表。对照"可改项"，问清或推断要换什么，比如文字、颜色、尺寸、数据、真实的异步任务。运动关系和验收行为保持不变。
2. **读那一节**：在 `references/samples.md` 里，提示词就是规格。要接进已有项目时，再读 `reference.html` 里对应的 `mountNN` 和 `Motion` 类，拿到准确的运动参考。
3. **实现**：沿用项目原有的技术栈（React 等）。弹簧直接用 `motion.js`，或者把 `Motion` 类搬过去。下面的硬规则每个样例都要遵守。
4. **保留测试钩子**：每节末尾列了 `data-form`、`data-part` 和 ARIA 钩子，交付物里留着它们，验收脚本靠它们定位元素。
5. **验收**：每个样例放一个独立页面，命名为 `NN.html`，然后运行 `node scripts/verify.mjs <目录>`，全部 ✓ 才算完成。不过的项附有实测值，按实测值修。脚本覆盖不到的手感，比如拉伸程度是否好看、文字是否清晰，要自己操作一遍或截图检查。

## 硬规则（10 个样例共用）

- **同一个元素做完整个变化**：按钮、卡片、指示器都只改自身的尺寸和位置，不能用两个元素交叉淡入淡出来冒充形变。
- **不用 scale 拉伸带文字的东西**：拉伸只改 left/right/width/height；scale 只用于整体的轻微抬升，比如 08 的 1.02，或者 06 的后退层。
- **打断不跳**：重定向时从当前的位置和速度出发（`Motion.set` 会先采样当前轨迹）。快速连续操作不能跳到上一个终点。
- **逻辑状态立即更新，画面跟着走**：aria-checked、aria-valuenow、列表顺序在触发的当下就变，动画只负责视觉。
- **直接操作不插值**：拖动时位置直接等于指针位置（`snap`）。松手后才用弹簧，并把拖动速度传进去（`set(…, {}, {x: v})`）。
- **按真实尺寸测量目标**：用 `getBoundingClientRect` 测量，适应长短不同的文字和移动端宽度。
- **减少动态效果**：`prefers-reduced-motion` 下直接到终态。`Motion` 已经处理了，自写的 CSS 动画要另外关掉。
- **键盘、触摸和语义**：按每节提示词里写明的 role 和 aria 做；触控目标不小于 44px；只在拖柄或滑块区域设置 `touch-action: none`。
- **视觉克制**：画布用暖灰 `#f2f1ed`，组件只用黑白；英文用 Geist（离线可回退到系统字体），图标描边 1.7px。只允许轻微超调，不加弹跳、光晕、粒子或界面渐变。用户点名要换风格时，可以套 `assets/skins/` 里的皮肤，见下一节；运动规则不变。
- **演示与接入分开**：01 的异步任务、07 的命令执行在演示时用明确的模拟结果；接入时换成真实操作，错误必须看得见、能重试。

## 皮肤

皮肤只通过测试钩子（`data-form`、`data-part`、ARIA 角色）定位元素，只改颜色、字体、边框和阴影，不碰带钩子元素的尺寸、位置、transform 和过渡，所以动效和验收结果都不受影响。用法：在样例自身的 CSS 之后引入皮肤文件，然后在 `<html>` 上设 `data-skin`。

| 皮肤 | 文件 | 样子 |
|---|---|---|
| HUD | `assets/skins/hud.css`，设 `data-skin="hud"` | 纸墨加薄荷强调色、压缩斜体大写标签、硬投影纸卡、网格底。整页 HUD 外壳用 `hud-interface` skill |

新写的皮肤要先套在 10 个参考实现上跑一遍 `verify.mjs`，155 项全过才能收进来。

## 弹簧参数（参考实现实测）

`Motion` 的阻尼比是 0.84，`w` 是角频率，越大越快。

| ID | 值与目标 | 速度 `w` |
|---|---|---|
| 01 | width / radius：196·16 → 58·29 → 166·16 | 22；文字先淡出 100ms（模糊 3px、上移 3px），再淡入 200ms |
| 02 | 指示器 left、right 各自独立 | 领先边 29，尾随边 18，反向时对调 |
| 03 | 视觉位置 x；越界延伸 `24·(1−e^(−越界距离/90))` | 松手时用 22，并带上拖动速度（限制在 ±900px/s） |
| 04 | 旋钮 left 5→33、right 39→67，底色 0→1 | 领先边 30，尾随边 17，底色 22 |
| 05 | 卡片高度 142 ↔ 278 | 22；展开时内容延后淡入并上移 6px；折叠时内容先在 120ms 内淡出，外壳再收起 |
| 06 | 每层 `y:−12i`、`scale:1−0.04i`、`opacity:1−0.16i`；新层从 `y:16, scale:.98, opacity:0` 进入 | 22 |
| 07 | 原生 `<dialog>`：进入 200ms，从 0.96 缩放加淡入；退出 140ms | CSS `cubic-bezier(.23,1,.32,1)` |
| 08 | 行 y = 序号 × 行距（74）；拖动时 scale 1.02 | 22；交换阈值是 `round(y/行距)` |
| 09 | 提示位置偏离指针 16px，离边界留 12px，靠边时翻转并夹紧 | 30 |
| 10 | `strokeDashoffset = 长度 × (1−progress)` | 8（约 800ms）|

## 适用边界

这些是可运行的交互参考，用浏览器原生的 HTML、CSS、SVG 和 JS 写成，没有接入任何业务。图谱里的其余 500 多个条目不在这里，只收了这 10 个经过验收的样例。

## 常见坑

- 原生 `<dialog>` 没有 `role` 属性也算 dialog。`showModal()` 自带焦点约束；关闭时要自己把焦点还给触发按钮。
- 06 的后层要同时设 `inert` 和 `aria-hidden`，隐藏正文和按钮。宣告新增用独立的 `aria-live="polite"` 区域，堆栈本身不要做成 live region。
- 08 要在松手时真正重排 DOM（或数据），只做 transform 不算完成。重排后要恢复焦点。
- 09 的提示层设 `pointer-events: none`，不要加 `filter` 或 `will-change`，否则文字会糊。
- 10 的竖向引导线和提示按横坐标找最近的数据点，不按到曲线的距离找。提示框夹紧在卡片内。

## 验收记录

2026-10-27 盲测：skill 副本去掉 `reference.html`，5 个子代理各只凭提示词做 2 个样例。

| 版本 | 结果 | 说明 |
|---|---|---|
| 原参考实现（补上测试钩子） | 10/10，155 项 | 用来校准验收脚本 |
| 盲测第一版（跑验收脚本前写好） | 9/10，154/155 项 | 06 漏了关闭时的宣告 |
| 盲测修正后 | 10/10，155/155 项 | 06 修了一轮，其余没改 |
| 反例（02 两边同速、06 层级写错） | 都判为不过 | 证明脚本能抓出错误 |

HUD 皮肤套在 10 个参考实现上：10/10，155 项全过（第一次跑时 01 因 Google Fonts 加载超时没打开页面；去掉测试副本里的字体链接后重跑通过，动效检查本身没有失败）。

盲测反馈的歧义已写进 `samples.md` 各节的"补充说明"。脚本覆盖不到的有：手感和观感、10 的空态、Safari 和 Firefox、真机触摸。
