From 齐码 · Vibe Coding 流水线
Writes zero-ambiguity interaction docs from an idea.md: per-page layout, modules, page states, element triggers/behaviors, and navigation classifications (modal, drawer, toast, etc.) with functional data requirements.
How this skill is triggered — by the user, by Claude, or both
Slash command
/qima:vibe-interactionThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> 整套 Vibe Coding skill 的**差异化灵魂**:把「用户在每个页面、每次点击会看到与触发什么」写到零歧义颗粒度。
整套 Vibe Coding skill 的差异化灵魂:把「用户在每个页面、每次点击会看到与触发什么」写到零歧义颗粒度。 SKILL.md 正文承载方法论、模板与对齐规则;详尽词表/字段规范/专业范式下沉到
references/,正文用「详见 references/.md」指向。
idea.md → interaction.md → architecture.md → design.md(视觉) → prototypes/ → 代码 中的第二环。输入 = idea.md(由 vibe-idea 产出);输出 = interaction.md(交互骨架,第一份 UI 文档),固定名、与 idea.md 同目录(项目根)。vibe-architecture 的职责,它会照本文件的数据需求派生),也不碰视觉设计准则 / 设计 token / 配色排版(那是 vibe-design 的职责)。它只负责把每个页面的布局、功能模块、页面逻辑、跳转逻辑、每个按钮/元素点击后的逻辑、弹窗逻辑(明确标注 弹窗 modal / 跳转 navigate / 浮窗 popover / 抽屉 drawer / 轻提示 toast 等)写到「任何实现者读完都能零歧义复现」的程度。interaction.md 是流水线里首次定义 页面ID / 模块ID / 元素ID 的文档(下游 architecture.md 之后引用它们)。它描述「用户在每个页面、每次点击看到与触发什么」,并功能化描述每页的数据需求(这页要展示什么数据=读、这次点击写什么=写),不写接口 ID(architecture.md 此时尚不存在,接口 ID 由其随后据此派生)。细化中若发现产品层缺口,回填上游 idea.md(沿用「以上游为权威主线」的回填裁决原则;见下文「完成判定」第 5 条)。它是整条主线里「最易遗漏、用户最看重」的一环,也是本套件相对通用 AI 编程的差异化核心。interaction.md 就绪后交给 vibe-architecture,它将照本文件的数据需求派生 architecture.md(数据模型 / 接口 / 安全规则,并定义接口 ID),其后再由 vibe-design(视觉)产出 design.md、vibe-prototype 依 design.md(视觉权威)+ interaction.md(元素/状态)出原型(顺序:idea 1 → interaction 2 → architecture 3 → design 视觉 4 → prototype 5)。正向触发:用户已有 idea.md,想把页面与元素的交互行为定义到可实现颗粒度——谈「设计交互 / 交互文档 / 页面逻辑 / 跳转逻辑 / 点了怎么跳 / 是弹窗还是跳转 / 弹窗还是新页面 / 把页面流程理清楚 / 每个按钮 / 每个元素 / interaction」。
反触发(相邻阶段抢入口时主动让路):
idea.md(产品意图尚未定型)→ 交给 vibe-idea;连产品想法都未收敛,更谈不上逐页逐元素交互。interaction.md 要据其派生技术骨架 / 数据模型 / 接口(architecture.md) → 交给 vibe-architecture;architecture.md 是本文件的下游,它照本文件功能化描述的数据需求派生数据模型与接口、并定义接口 ID。architecture.md 要做视觉设计准则 / 设计系统 / design.md(tokens、配色、排版、组件、Do&Don't) → 交给 vibe-design(视觉)。design.md(视觉)与 interaction.md 要画原型 / 出设计图 / 接 Stitch → 交给 vibe-prototype。vibe-implement。撰写 interaction.md 必须逐条遵守以下五条:
idea.md 同目录(项目根),命名固定为 interaction.md,不得改名。idea.md 的哪个版本/commit」(上游产品立项);每个页面的「数据需求」字段必须功能化描述读什么 / 写什么(如「展示订单列表=读」「点击删除=写一次订单删除」),不写接口 ID——接口 ID 由下游 architecture.md 据此派生定义,本文件不得在此另起接口定义、也不引用尚不存在的接口 ID。architecture.md 之后引用它们)。沿用贯穿全流水线的全局 ID 规范——页面 ID = 可读 kebab-case slug、模块 ID <页面ID>-M-<字母>、元素 ID <页面ID>-E-<字母>-<序号>;接口 ID API-<域>-<动作> 由下游 architecture.md 据本文件数据需求派生定义,本文件不出现。其中元素 ID 的 <字母> 是整页元素分组的序列字母,不必与模块字母一致(同一页面下不同模块的元素可共用一套 A/B/C… 字母序列,只要全页元素 ID 唯一即可;如下文示例里筛选栏 order-list-M-A 与订单表格 order-list-M-B 下的元素都用 E-A-* 系列)。全文件 ID 唯一;跳转关系、入口出口、门控矩阵、对齐互指一律用 ID。TBD、待定、具体见后续,以及其他英文待办词等拖延话术)或空表格;任何分支(成功 / 失败 / 空 / 无权限)都必须写出明确行为。navigate/modal/confirm/drawer/popover/bottomsheet/toast/inline-expand/inline-edit/newtab/download),违者视为规格不合格。正文留方法论与模板,细节下沉 references:
references/interaction-taxonomy.md。references/a11y.md。references/states-and-motion.md。references/generative-ui.md。interaction.md 由三套可直接复制的模板拼成:A. 全局信息架构(全文件一份)、B. 单页面规格(每个页面重复一份)、C. 功能模块 / 区块规格(每个模块一份)。下列骨架中的 <page-slug> / <page-slug>-M-A / <page-slug>-E-A-01 是模板占位(写真实页面时替换为真实 ID),不属于内容占位。
全文件唯一一份,声明站点地图、导航、跳转关系图、全局组件、全局状态,以及全局 a11y / 动效基线。
# 交互文档 interaction.md
> 对齐:idea.md @ <版本号/commit>
> 角色定义(贯穿全文):<访客 guest> / <普通用户 user> / <管理员 admin> / ...
## A. 全局信息架构
### A.1 站点地图 / 页面清单
| 页面ID | 页面名称 | 路由 | 所属域 | 默认可见角色 |
|--------|----------|------|--------|--------------|
| <page-slug> | <名称> | /path | <域> | <角色列表> |
### A.2 导航结构
- **顶部导航(Top Nav)**:<是否存在;包含项与各自指向的页面ID;是否随登录态变化>
- **侧边导航(Side Nav)**:<是否存在;层级;折叠规则;高亮当前页规则>
- **底部导航(Bottom Tab,移动端)**:<是否存在;Tab 项与指向页面ID>
- **面包屑(Breadcrumb)**:<规则>
### A.3 页面跳转关系图
```mermaid
flowchart LR
list[列表页] -->|点击行/查看| detail[详情页]
detail -->|返回| list
list -->|新建·drawer| list
```
> 注:drawer/modal 不产生路由跳转的,在图中以**自环 + 标注 "(drawer)/(modal)"** 表示,不画成新节点。
### A.4 全局组件(挂载于根布局,所有页面共享)
| 组件 | 类型 | 说明 | 触发来源 |
|------|------|------|----------|
| 全局导航栏 | Top Nav | 见 A.2 | 常驻 |
| 全局弹窗容器 | modal root | 承载所有 modal/二次确认 | 任意页面调用 |
| 全局抽屉容器 | drawer root | 承载所有 drawer | 任意页面调用 |
| 全局 Toast 容器 | toast root | 右上/顶部居中,**堆叠上限 3,默认 3s 自动消失** | 任意页面调用 |
| 全局 Loading 遮罩 | overlay | 仅用于阻断式全局操作 | 显式调用 |
| 会话过期拦截器 | modal | **401 时统一弹出"重新登录" modal** | 全局接口拦截 |
### A.5 全局状态(Global State)
| 状态 | 取值 | 影响范围 | 变更触发 |
|------|------|----------|----------|
| 登录态 isAuthed | true/false | 导航项可见性、受保护页面准入 | 登录/登出/401 |
| 当前角色 role | guest/user/admin | 元素级门控(见 §F) | 登录成功后写入 |
| 主题 theme | light/dark | 全局配色 | 用户切换/系统跟随 |
| 全局加载 globalLoading | true/false | Loading 遮罩 | 阻断式操作 |
### A.6 全局 a11y 基线(一处声明,各页继承,逐元素只标差异 —— 详见 references/a11y.md)
- **跳转链接 skip-to-content**:页首提供「跳到主内容」隐藏链接,键盘第一个 Tab 可达。
- **`lang` 属性**:根 `<html lang="zh-CN">`,多语言页随切换更新。
- **全局 focus-visible ring token**:沿用 **shadcn 组件变体体系(套件铁律基线)** 的 `focus-visible:ring-2 focus-visible:ring-ring`(Next.js+CloudBase+shadcn 固定基线,不依赖 `architecture.md` 已写),禁止 `outline:none` 而无替代。
- **最小对比度与触控目标规约**:正文对比度 ≥ 4.5:1、大字/图形/状态色 ≥ 3:1;触控目标 ≥ 44×44px。
- **读屏宣告策略**:`toast` 用 `aria-live="polite"`;路由切换后焦点移到新页主区/标题供读屏宣告页面变更。
### A.7 动效 token 基线(登记四类时长/缓动 token + 全局 reduced-motion 策略 —— 详见 references/states-and-motion.md)
| 动效类型 | 默认时长 | 缓动 | 典型用途 |
|---|---|---|---|
| enter(进场) | 150–200ms | ease-out | modal/drawer/popover 出现 |
| exit(退场) | 100–150ms | ease-in | 浮层关闭(略快于进场) |
| move(位移/重排) | 200–300ms | ease-in-out | 列表重排、inline-expand 展开 |
| feedback(反馈) | ≤100ms | ease-out | 按下、hover、开关切换 |
> 全局策略:token 单一来源在 **shadcn 组件变体体系(套件铁律基线)** 的 theme / CSS variables;`@media (prefers-reduced-motion: reduce)` 下位移/缩放降级为瞬时切换或极短 opacity 渐隐,关键状态变更保留、纯装饰关闭。逐元素只标「用哪档 + 回退」。
## <page-slug> <页面名称>
| 字段 | 内容 |
|------|------|
| 页面ID | <page-slug> |
| 路由 | /path/:id |
| 目的(一句话) | <用户在此页要完成什么> |
| 入口(从何而来) | 列出 来源页面ID + 触发元素ID(如 从 <other-slug> 的 <other-slug>-E-A-03 点击进入) |
| 出口(去往何处) | 列出 目标页面ID + 触发元素ID;含"返回"行为 |
| 设备/断点 | desktop / tablet / mobile 三档差异(若有) |
### 布局分区(Layout Regions)
- **Header**:<内容与高度行为>
- **Sidebar**:<内容;是否可折叠>
- **Main**:<主区域,通常承载核心模块>
- **Footer**:<内容;是否吸底>
### 所含功能模块
- <page-slug>-M-A <模块名>(见 §C)
- <page-slug>-M-B <模块名>
### 页面级状态 —— 状态矩阵(四态为必填底线,扩展态按数据生命周期补)
> `loading / empty / error / forbidden` 四态**必填**(空表格不通过);`partial / offline / stale / optimistic` 等扩展态**按本页数据生命周期补**。错误态用**功能化条件**描述(网络超时 / 401 未登录 / 403 无权限 / 5xx 致命 / 返回空集…),**由下游 `architecture.md` 据此定义错误码**;本文件不写错误码。
| 状态 | 触发条件(功能化) | 呈现(绑定下文「呈现方式分类法 Taxonomy」/ shadcn) | 可恢复性分级 |
|------|----------|-------------------------------------|--------------|
| 加载中 loading | 进入页/数据请求中(结构已知) | 骨架屏 Skeleton,指明范围 | — |
| 空 empty | 数据返回空集 | 空状态插画 + 文案 + 主行动按钮ID | — |
| 错误 error · 可重试 | 网络/超时 | 错误占位 + "重试"按钮,点击重新请求 | 可重试 |
| 错误 error · 需登录 | 401 未登录 / 会话过期 | 会话过期 modal 或 navigate 登录(沿用 A.4 拦截器) | 需登录 |
| 错误 error · 致命 | 5xx 服务端致命 / 数据损坏 | 错误占位 + 反馈入口,不提供"重试" | 致命 |
| 无权限 forbidden | 403 无权限 / 角色不满足 | 403 占位 / 重定向到 <other-slug>(二选一并写明) | 需提权 |
| 部分加载 partial | 分页/分块到达 | 已到区块渲染 + 剩余 Skeleton / "加载更多"按钮 | — |
| 离线 offline | 断网 | 全局/局部离线条;写操作禁用并 toast 提示 | — |
| 旧数据 stale | 缓存有效、后台刷新 | 直接展示旧数据 + 极轻"更新中"指示 | — |
| 乐观更新 optimistic | 写操作发起 | 就地预渲染结果 + loading 小态;失败回滚 + toast"已撤销" | 可重试 |
### 数据需求(读/写,供 architecture 派生)
> 功能化描述这页**读什么 / 写什么**,不写接口 ID;下游 `architecture.md` 据此派生数据模型与接口、并定义接口 ID 回标到这些数据需求。
| 数据需求描述(读什么/写什么) | 时机 | 失败回退 |
|------|------|----------|
| <读:展示什么数据 / 写:这次动作写什么> | 进入页加载 | 进入 error 态 |
每个独立取数的数据块,追加一张块级状态矩阵(列:
状态 | 触发(功能化) | 呈现 | 可恢复性分级),口径同模板 B 的状态矩阵;触发用功能化条件描述、不写错误码(由 architecture 据此定义);无独立取数的纯展示块可省略。
### <page-slug>-M-A <模块名>
- **用途**:<这个区块解决什么>
- **位置**:<在哪个布局分区>
- **元素清单**:
| 元素ID | 元素名 | 类型 |
|--------|--------|------|
| <page-slug>-E-A-01 | 新建按钮 | button |
| <page-slug>-E-A-02 | 搜索框 | input |
| <page-slug>-E-A-03 | 数据行 | row/card |
- **块级状态矩阵**(仅当本模块独立取数时):
| 状态 | 触发(功能化) | 呈现 | 可恢复性分级 |
|------|------|------|--------------|
| loading | 模块取数中 | 区块 Skeleton | — |
| empty | 数据返回空集 | 区块空插画 + 文案 | — |
| error | 取数失败(网络/超时) | 区块错误占位 + 重试 | 可重试 |
每个「行为」在改变视觉层级时,必须且只能标注下列 11 个关键字之一。下面给出关键字清单 + 一句话语义作为正文速查;每个关键字的「是否改变路由 / 是否阻断」等完整四列定义、shadcn 映射与决策规则的单一事实源在 references/interaction-taxonomy.md,正文与之冲突时以 reference 为准。
navigate —— 页面跳转:进入新页面/路由,产生历史记录、可后退(整页替换)。modal —— 模态弹窗:居中浮层 + 遮罩,需用户处理后关闭(遮罩阻断)。confirm —— 二次确认弹窗:modal 的特例,仅"确认/取消"两按钮,用于危险操作(阻断)。drawer —— 抽屉:从边缘(右/左/上/下)滑入的面板,保留上下文(半阻断,可带遮罩)。popover —— 浮层气泡:锚定在触发元素旁的小浮层,点外部即关(不阻断)。bottomsheet —— 底部动作条:移动端从底部升起的动作面板(半阻断)。toast —— 轻提示/snackbar:短暂非阻断反馈,自动消失,不打断操作(不阻断)。inline-expand —— 原地展开/手风琴:在当前位置展开更多内容(折叠面板/嵌套行,不阻断)。inline-edit —— 原地编辑:字段就地变为可编辑态,失焦/回车保存(不阻断)。newtab —— 新标签页:在浏览器新标签打开,不离开当前页(新窗口)。download —— 下载:触发文件下载,无页面跳转(不阻断)。references/interaction-taxonomy.md)每个呈现方式只能落到一个确定的 shadcn 组件 variant,零自造——一律继承自 components/ui(沿用 shadcn 组件变体体系(套件铁律基线),Next.js+CloudBase+shadcn 固定基线,不依赖 architecture.md 已写),vibe-implement 实现时严禁为这些呈现方式手写组件。逐一映射为:navigate→路由(Next App Router <Link>)、modal→Dialog、confirm→AlertDialog(危险操作专用,主按钮 destructive variant)、drawer→Sheet、popover→Popover / DropdownMenu、bottomsheet→Drawer(vaul)/ 移动端 Sheet side="bottom"、toast→Sonner、inline-expand→Accordion / Collapsible、inline-edit→就地 Input + Form、newtab→<a target="_blank" rel="noopener noreferrer">、download→<a download>。
一句话铁律(零自造):标注了某 taxonomy 关键字却未用上面对应的 shadcn 组件实现的,视为不合规;变体继承自
components/ui,沿用 shadcn 组件变体体系(套件铁律基线) 「变体只增不散」。
决策规则要点(「何时用哪种」,实现者据此自检;完整 10 条详见 references/interaction-taxonomy.md):独立内容 / 需专属 URL 可分享或可后退 → navigate;少量信息确认或 ≤5 字段简单表单且必须当场处理 → modal;危险/不可逆操作(删除、清空、注销)必须 → confirm(后果文案明确、主按钮危险色);复杂表单 / 多字段编辑、希望边看列表边填 → drawer;辅助说明 / 快捷菜单 / 轻量选择 → popover(桌面)/ bottomsheet(移动端);非阻断结果反馈(保存成功、复制成功、网络错误)→ toast(不要用 modal 报"成功");同上下文看更多明细 → inline-expand;单字段快速修改 → inline-edit;跳外部站点/文档/政策页 → newtab;导出报表/下载附件(规则 10)→ download。
互斥提示:同一操作不得同时标注两个关键字;若"保存成功后跳转",写成带顺序的行为序列:
提交 → 成功 toast → navigate(<target-slug>),并标注顺序。
每个可交互元素一份规格,呈现方式标注唯一。除核心字段外,按下文「交互专业深化」追加 a11y 标注(键盘 / aria / 焦点去向)与动效标注(类型 / 时长 / 缓动 / reduced-motion 回退);表单输入类额外填校验规则表。
#### <page-slug>-E-A-01 <元素名> · <类型>
- **触发**:<点击 click / 长按 / hover / 输入 input / 滚动 scroll / 失焦 blur>
- **前置条件**:<是否需登录;是否需选中项;是否表单校验通过>
- **行为**:<一句话动作> 【呈现方式:`<taxonomy 关键字>`(目标=…,位置=…)】
- **行为序列(如有多步)**:① … → ② … → ③ …
- **多状态**:
| 状态 | 视觉/文案 | 可点 |
|------|-----------|------|
| 默认 default | … | 是 |
| hover | … | 是 |
| 按下 pressed | … | 是 |
| 禁用 disabled | … + 禁用原因 tooltip(popover) | 否 |
| 加载中 loading | spinner + 文案"处理中",防重复提交锁定 | 否 |
| 成功 success | toast"…成功" | — |
| 失败 error | toast"…失败:<原因>",可重试 | 是 |
- **门控**:可见角色=<…>;可用角色=<…>(见 §F)
- **边界与异常**:<空数据/超长/网络失败/并发/防重复>(见 §G)
- **a11y**:键盘=<Tab 可达 / Enter|Space 激活 / ESC 关闭>;aria=<role / aria-label|labelledby / aria-expanded|invalid|describedby / aria-live 级别>;焦点去向=<打开后焦点落在? 关闭后归还到哪个元素ID?>(详见 references/a11y.md)
- **动效**:类型=<enter|exit|move|feedback>;时长=<token,如 enter-200ms>;缓动=<ease-out|ease-in|ease-in-out>;reduced-motion 回退=<瞬时切换 / opacity 渐隐 / 关闭装饰>(详见 references/states-and-motion.md)
表单输入类元素额外填写校验规则:
- **校验规则**:
| 规则 | 时机 | 错误文案 | 呈现 |
|------|------|----------|------|
| 必填 | 提交时 | "请输入<字段>" | 字段下方红字 inline |
| 格式(邮箱) | 实时(blur) | "邮箱格式不正确" | inline |
| 长度≤50 | 实时(input) | "最多 50 字"(超出禁止再输入) | 计数器变红 inline |
### F. 权限门控矩阵
| 元素ID | guest | user | admin | 不满足时 |
|--------|-------|------|-------|----------|
| <page-slug>-E-A-01 新建 | 隐藏 | 可用 | 可用 | guest 不渲染该按钮 |
| <page-slug>-E-A-04 删除 | 隐藏 | 禁用(disabled+tooltip) | 可用 | user 置灰并提示"无权限" |
### G. 边界与异常约定
| 场景 | 规则 |
|------|------|
| 空数据 | 走页面 empty 态;列表内空走模块空插画 |
| 超长文本 | 单行省略号 + hover popover 全文;多行最多 N 行后"展开"(inline-expand) |
| 网络失败 | toast 报错 + 元素回到默认态;列表级失败走 error 态可重试 |
| 并发冲突 | 提交遇"数据已被他人修改"(架构据此定义为 409 类错误)→ confirm"数据已被他人修改,是否覆盖?" |
| 防重复提交 | 提交瞬间元素进入 loading 并禁用,请求结束才恢复 |
| 二次确认 | 所有危险操作走 confirm,主按钮危险色,默认焦点在"取消" |
「列表页 + 详情/编辑」典型场景的完整填写示范,展示按钮点击 →
modal/navigate/drawer/toast/confirm的精确写法。实现者照此即可零歧义落地。
flowchart LR
order-list[订单列表页] -->|点击订单行 order-list-E-A-03| order-detail[订单详情页]
order-list -->|新建订单 order-list-E-A-01 · drawer| order-list
order-list -->|编辑 order-list-E-A-05 · drawer| order-list
order-list -->|删除 order-list-E-A-06 · confirm| order-list
order-detail -->|返回 order-detail-E-D-01 · navigate| order-list
| 字段 | 内容 |
|---|---|
| 页面ID | order-list |
| 路由 | /orders |
| 目的 | 查看、检索、创建、管理订单 |
| 入口 | 顶部导航"订单"项;登录成功后默认落地页 |
| 出口 | 点击订单行 → navigate 至 order-detail;返回顶导其他页面 |
| 设备/断点 | desktop:表格;mobile:卡片列表,操作收进 bottomsheet |
布局分区
order-list-E-A-01 新建订单 按钮。order-list-M-A 筛选栏 + order-list-M-B 订单表格。所含功能模块:order-list-M-A(筛选栏)、order-list-M-B(订单表格)。
页面级状态
| 状态 | 触发(功能化) | 呈现 |
|---|---|---|
| loading | 进入页/筛选请求中 | 表格区骨架屏(8 行) |
| empty | 订单列表返回空集 | 空状态插画 + 文案"暂无订单" + 复用 order-list-E-A-01 作为主行动 |
| error | 读订单列表失败(网络/超时) | 表格区错误占位 + "重试"按钮,点击重新请求 |
| forbidden | role=guest(未登录) | 重定向到登录页 login |
数据需求(读/写,供 architecture 派生)
| 数据需求描述(读什么/写什么) | 时机 | 失败回退 |
|---|---|---|
| 读:订单列表(支持按关键词/状态筛选、分页) | 进入页/筛选/翻页 | error 态 |
| 写:删除指定订单 | 点击删除并确认后 | toast 报错,行保持 |
| 写:创建一条订单 / 更新一条订单(含状态字段) | drawer 提交 / 行内切换 | 字段级或 toast 报错 |
order-list-M-A 筛选栏
order-list-E-A-01 新建订单(button)、order-list-E-A-02 关键词搜索(input)、order-list-E-A-07 状态下拉(select)。order-list-M-B 订单表格
order-list-E-A-03 订单行(row)、order-list-E-A-05 编辑(button)、order-list-E-A-06 删除(button)、order-list-E-A-08 状态切换(switch)。触发:click。
前置条件:已登录。
行为:打开"新建订单"表单面板。【呈现方式:drawer(目标=新建订单表单,位置=右侧滑入,宽 480px,带遮罩)】
行为序列:① 点击 → drawer 右滑入 → ② 填写并点 drawer 内"保存" → ③ 【写:创建一条订单】发起,按钮进 loading → ④ 成功:toast"创建成功" + drawer 关闭 + 列表刷新;失败:字段级错误 inline,无法定位字段的错误走 toast。
多状态
| 状态 | 视觉/文案 | 可点 |
|---|---|---|
| default | 主色实心"+ 新建订单" | 是 |
| hover | 加深 8% | 是 |
| pressed | 下沉 1px | 是 |
| disabled | 置灰(仅 guest,实际 guest 不可见) | 否 |
| loading | 指 drawer 内"保存"按钮:spinner+"保存中",锁定防重复 | 否 |
门控:可见=user/admin;guest 不渲染。
边界:drawer 内防重复提交(loading 锁定);关闭未保存时,若已编辑过 → confirm"放弃未保存的内容?"。
a11y:键盘=Tab 可达 / Enter|Space 打开;焦点去向=drawer 打开后焦点落首个输入框,关闭后归还到 order-list-E-A-01;aria=Sheet 内建 role=dialog+aria-modal,标题经 aria-labelledby 关联。
动效:类型=enter;时长=drawer enter-200ms;缓动=ease-out;reduced-motion 回退=瞬时切换。
navigate(目标=order-detail,路由 /orders/:id)】
order-list-E-A-05 / order-list-E-A-06 / order-list-E-A-08 等操作元素时不触发行跳转(事件需 stopPropagation)。navigate 后焦点移到 order-detail 主区标题供读屏宣告。drawer(目标=编辑表单,右侧滑入,复用新建 drawer,模式=edit)】toast"已保存" + 关闭 + 该行局部刷新;失败:toast"保存失败:<原因>",drawer 不关,保留输入。confirm"该订单已被他人修改,覆盖将丢失对方改动,是否继续?"(主按钮危险色)。confirm(标题"删除订单 #<编号>?",正文"删除后不可恢复",主按钮"删除"危险红,默认焦点在"取消")】confirm 弹出 → ② 点"删除" → 【写:删除该订单】,confirm 主按钮进 loading → ③ 成功:toast"已删除" + confirm 关闭 + 该行移除(列表空则转 empty 态);失败:toast"删除失败:<原因>",行保留,confirm 关闭。popover 提示"无删除权限"。toast"该订单已不存在" + 移除该行。confirm 默认焦点落"取消",危险主按钮用 Button destructive variant;关闭后焦点归还 order-list-E-A-06。inline-edit(就地切换,乐观更新)+ 结果 toast】toast"状态已更新";失败:switch 回滚到原值 + toast"更新失败,已撤销"。触发:input(防抖 400ms)/回车。
行为:重新请求列表(就地刷新,不跳转、不弹层)。【呈现方式:无层级变化;列表区 loading→刷新】
校验规则
| 规则 | 时机 | 错误文案 | 呈现 |
|---|---|---|---|
| 长度≤50 | 实时 input | "搜索词最多 50 字"(超出禁止再输入) | 输入框右侧计数器变红 inline |
| 允许为空 | — | (清空=取消筛选,展示全部) | — |
边界:防抖期间快速连打,仅最后一次生效(请求竞态取最新);搜索无结果 → 列表区局部 empty"未找到匹配订单"。
popover(锚定在下拉框下方,点外部即关)】;选中某项 → popover 关闭 + 触发列表刷新。popover 键盘可达(focus 即触发,非仅 hover),ESC 关闭,焦点回锚点;aria-expanded 随开合变化。| 元素ID | guest | user | admin | 不满足时 |
|---|---|---|---|---|
| order-list-E-A-01 新建 | 隐藏 | 可用 | 可用 | guest 不渲染 |
| order-list-E-A-05 编辑 | 隐藏 | 仅本人订单可用,他人订单 disabled | 全部可用 | disabled + hover popover"无编辑权限" |
| order-list-E-A-06 删除 | 隐藏 | 仅本人可用 | 全部可用 | disabled + popover"无删除权限" |
| order-list-E-A-08 状态切换 | 隐藏 | 仅本人可用 | 全部可用 | disabled |
| 场景 | 规则 |
|---|---|
| 空数据 | 列表空→页面 empty 态;搜索/筛选无果→列表区局部 empty 文案 |
| 超长文本 | 订单备注单行省略号,hover popover 全文 |
| 网络失败 | 列表请求失败→error 态可重试;行内操作失败→toast 报错并回滚乐观更新 |
| 并发冲突 | 编辑保存遇"已被他人修改"→confirm 覆盖确认;删除遇"已不存在"→toast"已不存在"并移除行(架构据此定义对应错误码) |
| 防重复提交 | 新建/编辑保存、删除确认,点击即 loading 锁定至请求返回 |
| 二次确认 | 删除走 confirm;drawer 有未保存改动时关闭走 confirm |
零歧义验收口径:对本示例中任意按钮提问"点了之后是弹窗/跳转/抽屉/浮窗/提示?"——新建/编辑=
drawer,订单行=navigate,删除=confirm,状态切换=inline-edit+toast,状态筛选=popover,搜索=就地刷新无层级。每个答案在规格中均有唯一标注,无第二种解读。
在前文「模板 A 全局信息架构」到「完整示例」各模板之上追加四类强制深化字段,把 vibe-interaction 从「能写清呈现方式」拔高到「专业、可验证、AI 时代」的水准。深化只增标注,不另起词表——沿用本文件 ID 规范、上文「呈现方式分类法 Taxonomy」词表与 shadcn 组件变体体系(套件铁律基线,shadcn variant)。
| 类别 | 适用范围 | 落点 | 细则 |
|---|---|---|---|
| A 无障碍(WCAG 2.1 AA) | 所有产品 | 每个可交互元素 +1 行 a11y 标注;全局 A.6 基线 | 详见 references/a11y.md |
| B 状态体系化(状态机) | 所有产品 | 页面级状态表扩为状态矩阵;每个独立取数块 +1 张块级状态矩阵 | 详见 references/states-and-motion.md |
| C 微交互动效 | 所有产品 | 有动效的元素/浮层 +1 行动效标注;全局 A.7 token 基线 | 详见 references/states-and-motion.md |
| D Generative UI | 仅 AI / 对话 / agent 产品 | 单页面规格后新增「Generative UI 规格」节 | 详见 references/generative-ui.md |
A/B/C 对所有产品强制生效;D 对 AI / 对话 / agent 类产品强制生效(尤其落地上游 idea.md 所承载的 AI 时代四透镜中的透镜一「流变重构」、透镜三「人即环境」、透镜四「可验证黑盒」的产品)。
D 节为 AI 页新增的「Generative UI 规格」字段清单(完整范式与 tool→组件映射详见 references/generative-ui.md):
useChat(客户端 tool-call 渲染 shadcn)/ streamUI(RSC,需说明为何采用);agent 后端 = CloudBase 云函数 / 云托管。tool | 渲染组件/variant | 触发数据(功能化:读什么/写什么,供 architecture 派生) | 失败回退。interaction.md 满足以下全部 7 条才视为「已就绪」,方可进入技术骨架(architecture)派生阶段:
architecture.md 据此派生)。idea.md 并由用户确认;头部「对齐:idea.md @ <版本/commit>」已更新到回填后版本。interaction.md 路径,用户复核并批准后才置状态为「已就绪」。interaction.md 的路径(./interaction.md)与当前版本/commit,以及其对齐到的上游 idea.md 版本/commit(下游派生与对齐以此为锚)。vibe-architecture 据此派生数据模型、接口与行级安全规则,并定义接口 ID 回标到每个页面/元素/动作。"
interaction.md已就绪并经你确认(路径:./interaction.md,对齐idea.md版本:<commit>)。下一步请手动调用 vibe-architecture,它将以idea.md+ 本文件为输入,照本文件的数据需求派生architecture.md(数据模型 / 接口三形态 / 行级安全规则,并定义接口 ID、为每个接口与可见字段标注服务于本文件的哪个页面/元素/动作),并与本交互文档做确定式全覆盖对齐矩阵;其后再由vibe-design(视觉)产出design.md、vibe-prototype依design.md(视觉权威)+ 本文件出每页原型(顺序:idea 1 → interaction 2 → architecture 3 → design 视觉 4 → prototype 5)。"
interaction.md / architecture.md / design.md(视觉) / prototypes/ / 最终路由的同一主键(本文件首次定义)。下游 vibe-architecture 以本文件的每个数据展示(读)、每个写入(写)、每条数据(security rules)为锚做确定式全覆盖派生,证明无缺口;architecture.md 派生时若发现本文件需求歧义 / 不可行,回指 vibe-interaction 澄清/修订 interaction.md(或上游 idea.md),architecture.md 不自行编造需求。回填裁决方向以上游为权威主线:idea.md > interaction.md > architecture.md。vibe-interaction 不自动拉起 vibe-architecture;它只把「就绪状态 + 路径 + 下一步指令」交还给用户,由用户手动发起下一阶段。npx claudepluginhub idiotleolyj/daliu-awesome-skills --plugin qimaDesigns user flows, micro-interactions, and interface behavior patterns with state management for loading, empty, error, and success states.
Derives data models, API contracts, and architecture from interaction.md for a fixed Next.js + CloudBase + shadcn/ui stack. Outputs architecture.md with database design, interface definitions, and full traceability to interaction elements.
Designs accessible interactive states, transitions, animations, error handling, loading patterns, and feedback for UI elements, covering visual, screen reader, keyboard, and touch interactions.