@agentaily/storybook-addon-review
在 Storybook 预览里 hover 选元素 → 写评论 → 一键开 GitHub PR(把评审笔记带过去)。第一刀面向本地
storybook dev。
做设计/组件评审时,不用再「描述我说的是哪个东西」——直接在预览里点中它、写下意见,攒一批后一键开一个 PR,PR 里是一份结构化的评审笔记(story id + 元素定位 + 评论)。
这是什么 / 怎么工作
三段式 Storybook addon(零构建:直接 ship 源码,由 Storybook 自己的 builder 打包):
| 入口 | 跑在哪 | 干什么 |
|---|---|---|
preview.jsx | 预览 iframe(Vite/plugin-react) | 一个 decorator:评审模式开时挂载 overlay —— hover 高亮、点选元素、弹框写评论 |
manager.jsx | Manager 外壳(esbuild,classic JSX) | 工具栏「● 评审」开关 + 「评审 (Review)」面板(评论列表 + Create PR) |
preset.js | dev server(Node) | experimental_serverChannel:收到 create-pr 就用本机 git + gh 开 PR |
数据流:overlay 选元素+评论 → channel add-comment → manager 面板累积 → 点 Create PR → channel create-pr → preset(Node) git/gh → channel pr-result → 面板显示 PR 链接。
「Create PR」如何不打扰你的工作树:preset 用 git plumbing 凭空造提交(hash-object → 临时 index → write-tree → commit-tree → branch),从不切分支、不碰工作树。新分支 review/<时间戳> 以 origin/main 为父,所以 PR 里只有一份 reviews/<时间戳>.md。
装 / 接入(本仓已接好)
已作为 workspace 包接进 design-system 的 Storybook:
pnpm-workspace.yaml列入storybook-addon-reviewdesign-system/package.jsondevDependency:"@agentaily/storybook-addon-review": "workspace:*"design-system/.storybook/main.js的addons数组加了"@agentaily/storybook-addon-review"
Storybook 的 addon 解析器会从本包
package.json的exports(./manager/./preview/./preset) 自动各接一次。所以preset.js绝不能再声明managerEntries/previewAnnotations,否则 preview 被注册两遍、构建报「has already been declared」。
用
pnpm --filter @agentaily/design-system storybook # 起本地 dev- 打开某个 story → 顶部工具栏点 ● 评审 进入评审模式。
- 在预览里把鼠标移到要评的元素上(高亮框 + 组件名角标)→ 点击选中 → 弹框里写意见 → 添加评论(⌘/Ctrl+Enter)。可多选多条。
Esc取消选中 / 再按退出评审。 - 右侧 评审 (Review) 面板看累积的评论;点 Create PR → 稍候面板给出 PR 链接。
- 「清空」清掉本轮评论。
本地 dev vs 静态/线上(优雅降级)
- 本地
storybook dev:有 Node server channel → 面板显示「● 本地 dev:可建 PR」,Create PR 可用。 - 静态构建 / 线上(
build-storybook,如storybook.agentaily.com):没有 Node → 面板探测不到 server channel(ping 无 pong)→ 显示「● 静态/线上:仅查看」,Create PR 禁用并提示。UI 仍可正常选元素 + 写评论,静态构建不会因本 addon 报错。
元素定位(无截图也能指到东西)
每条评论记录一个「定位」:优先 data-testid / 稳定 id / data-mk-label,否则一段短 CSS 路径;并尽力从 React fiber 读出最近的组件名,加上 tag / class / 文本片段 / 位置矩形。写进笔记 markdown,让 PR 读者不靠截图也能找到「说的是哪个」。
TODO / 后续
- 线上建 PR(线上后端):当前 Create PR 只在本地 dev(靠本机 git+gh)。线上(storybook.agentaily.com 静态托管,无 Node)要建 PR,需一个 Cloudflare Worker 后端 + GitHub App/token:addon 改为在静态环境下把 payload POST 给 Worker,Worker 用 GitHub API(创建 blob/tree/commit/ref + PR)开 PR。降级提示已就位,接上后端即可点亮。
- 截图:现仅记录元素矩形 + 定位,未附真实截图。后续可接
html-to-image/modern-screenshot抓选中元素截图并作为 PR 附件/内联图。 - PR 去重 / 续写:当前每次 Create PR 都开新分支新 PR;后续可支持往同一评审 PR 追加。
设计取舍
- 没复用 DS
MarkupLayer组件本体:它只认 opt-in 的data-mk-label元素,而本 addon 要选任意 story 里的任意元素;且复用它会让 addon 强依赖@agentaily/design-system,与「独立包」相悖。所以借用其视觉语汇(高亮框/角标/胶囊/弹框),targeting + locator + CSS 全部自包含。 - 零构建:直接 ship
.jsx源,靠 Storybook 自己的 manager(esbuild classic JSX)/preview(vite) builder 打包。故manager.jsx必须import React(classic runtime)。
自测
node scripts/smoke-create-pr.mjs # 真开一个评审 PR,打印 JSON(含 url/branch)
node scripts/smoke-create-pr.mjs --close # ...建完顺手关 PR + 删分支