十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Storybook 9 技能体系深度解析:storybook-story-instructions.md 如何教会 AI Agent 编写高质量 Story

Storybook 9 技能体系深度解析:storybook-story-instructions.md 如何教会 AI Agent 编写高质量 Story Storybook 9 技能体系深度解析storybook-story-instructions.md 如何教会 AI Agent 编写高质量 Story【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook本篇指南聚焦 Storybook 仓库中 AI 技能Skills体系的核心模板文件 storybook-story-instructions.md——它是 Storybook 交付给 AI Agent如 Claude Code、Codex 等编码助手的写 Story 操作手册。读完后你将掌握Agent 编写 Story 的完整方法论状态覆盖、交互测试、Mock、命名规范、Storybook 9 相对旧版本的关键破坏性变更包合并、initialGlobals、tags 驱动 autodocs、storybook/test导入、Play Function 参数语义以及这套模板如何被 build-story-instructions.ts 按项目实际配置动态渲染、经 MCP 或 CLI 两种通道下发到 Agent。一、模板定位write-story 技能的单一事实来源1.1 技能 ID 与冻结契约该模板文件在 Storybook 9 的 CLI/MCP 技能体系中对应write-story技能。技能 ID 定义在 skills.ts 中export const SKILL_IDS [stories, write-story, setup] as const; export const SKILLS: RecordSkillId, { blurb: string } { // ... write-story: { blurb: How to write, update, and test Storybook stories for this project: imports, patterns, and conventions., }, // ... };源码注释明确说明这些 ID 是公开的 CLI 词汇——插件存根会引用它们因此重命名视为破坏性变更。write-story技能的定位即如何为本项目编写、更新和测试 Story导入、模式与约定强调项目特异性——这正是模板中需要占位符动态填充的原因。1.2 双通道下发MCP 工具与 CLI 命令同一份模板有两条到达 Agent 的路径映射关系定义在 skill-refs.ts/** * Frozen contract: the name must match GET_UI_BUILDING_INSTRUCTIONS_TOOL_NAME * in addon-mcps tools/tool-names.ts. */ const MCP_SKILL_TOOL_NAMES: PartialRecordSkillId, string { write-story: get-storybook-story-instructions, }; export function getSkillRef(transport: SkillTransport) { return (id: SkillId): string (transport mcp MCP_SKILL_TOOL_NAMES[id]) || npx storybook skills get ${id}; }MCP 通道addon-mcp 注册了名为get-storybook-story-instructions的工具与 addon-mcp 中tool-names.ts的冻结常量一致可参见 tool-names.ts 与 get-storybook-story-instructions.test.tsAgent 在写 UI 前调用它获取完整指令。CLI 通道用户可执行npx storybook skills get write-story直接拉取渲染后的指令文本。为什么双通道必须表述同一工作流build-story-instructions.ts 中的注释解释了一处关键设计MCP 客户端如 Claude Code会截断服务端指令截断上限 2,048 字符因此服务端指令只保留简略指针而完整规则必须放在本模板输出里——因为该工具的输出从不被截断且是所有 Agent 在写 UI 前都会读取的唯一通道。这一工程取舍直接体现在 build-server-instructions.ts 的getFinalLinksGuidance实现中。二、模板正文Agent 写 Story 的方法论2.1 组件拆分与必有 Story原则模板开篇即给出两条硬性规则编写 UI 时优先把大组件拆分为更小的部分任何写出的组件都必须有 Story编辑组件时确保该组件的 Story 做了相应修改。这是 Agent 工作流的总纲Story 不是可选产物而是组件交付物的一部分。2.2 好 Story 的七项标准模板将什么是好 Story拆解为可执行清单核心目标是覆盖组件能到达的每一段独立业务逻辑与状态happy path、错误/边缘态、加载中、权限/角色、空态、props/context 带来的变体同时避免展示相同逻辑的冗余 Story。七个维度如下维度要求交互性组件可交互时必须用 play function 编写 Interaction 测试借助fn、userEvent、expect等storybook/test工具驱动 UI模拟点击、输入、focus/blur、键盘导航、表单提交、异步响应、toggle/选择变化、分页/过滤等。特别强调把fn作为回调 args 传入时play function 必须断言该回调确实被调用数据与搭建提供真实的 props、state 与 mock 数据包含有意义的标签/文本让行为可观测用确定性 fixture 桩掉网络/服务保证 Story 可重复渲染断言在 play function 中断言交互的可见结果文本、aria 状态、启用/禁用、class/状态变化、触发的事件优先使用基于 role/label 的查询变体只选取会改变行为的变体默认/主题切换、loading/loaded/empty/error、合法/非法输入、权限/角色/能力、feature flag、改变逻辑的尺寸/密度/布局可访问性使用语义化 role/label焦点与键盘交互在相关处必须有测试覆盖命名与结构Story 名描述场景如 Error state after failed submit相关变体逻辑分组不重复导入与格式Meta/StoryObj从框架包导入测试工具从storybook/test导入而非storybook/testStory 保持最小化只含演示行为所需的元素2.3 Storybook 9 关键变更Story 编写视角模板的 Storybook 9 Essential Changes for Story Writing 一节是版本迁移的核心要点Agent 写代码前必须先内化这些差异包合并Meta / StoryObj 与测试工具导入- import { Meta, StoryObj } from storybook/react; import { Meta, StoryObj } from storybook/react-vite;- import { fn } from storybook/test; import { fn } from storybook/test;注意第一个 diff 中的包名是占位符{{FRAMEWORK}}框架包如storybook/react-vite与{{RENDERER}}渲染器包如storybook/react由渲染器解析后填入映射表见 framework-renderer.tsexport const frameworkToRendererMap: Recordstring, string { storybook/react-vite: storybook/react, storybook/react-webpack5: storybook/react, storybook/nextjs: storybook/react, storybook/vue3-vite: storybook/vue3, storybook/sveltekit: storybook/svelte, // ... angular / preact / web-components / html 等 };从源码结构看该映射并非完备源码注释自述 its not complete未命中时buildStoryInstructions回退为renderer ?? frameworkToRendererMap[framework] ?? framework即直接把框架名当作渲染器名。全局状态globals重命名为initialGlobals// .storybook/preview.js export default { - globals: { theme: light } initialGlobals: { theme: light } };autodocs 配置用 tags 取代parameters.docs.autodocs// .storybook/preview.js 或单个 story export default { tags: [autodocs], // 为所有 story 生成 autodocs };Storybook 中的 Mocksb.mock两步走模板要求始终 Mock 外部依赖以保证 Story 渲染一致性并给出两步流程在 preview 文件中注册模块 Mocksb.mock建议{ spy: true }保留原函数同时可覆盖、可监听import { sb } from storybook/test; // Prefer spy mocks (keeps functions, but allows to override them and spy on them) sb.mock(import(some-library), { spy: true }); // Important: Use file extensions when referring to relative files! sb.mock(import(./relative/module.ts), { spy: true });注意模板特别强调引用相对文件时必须带文件扩展名——这是 Vite 环境下模块解析的硬性要求。在 Story 中用beforeEachmocked()指定 Mock 值import { expect, mocked, fn } from storybook/test; import { library } from some-library; const meta { component: AuthButton, beforeEach: async () { mocked(library).mockResolvedValue({ user: data }); }, }; export const LoggedIn: Story { play: async ({ canvas }) { await expect(library).toHaveBeenCalled(); }, };执行前提对应的 import 必须已在 preview 文件中完成sb.mock注册模板原文 Before doing this ensure you have mocked the import in the preview file。Play Function 参数语义canvasvscanvasElement这是模板中纠正 Agent 高发错误的一节play function 的canvas参数可直接使用 testing-library 风格的查询方法getByLabelText等canvasElement才是真正的 DOM 元素从storybook/test导入的within把 DOM 元素转换成带查询方法的对象与canvas等价。绝对不要写within(canvas)——canvas已具备查询方法它不是 DOM 元素// ✅ Correct: Use canvas directly play: async ({ canvas }) { await canvas.getByLabelText(Submit).click(); }; // ⚠️ Also acceptable: Use canvasElement with within import { within } from storybook/test; play: async ({ canvasElement }) { const canvas within(canvasElement); await canvas.getByLabelText(Submit).click(); }; // ❌ Wrong: Do NOT use within(canvas) play: async ({ canvas }) { const screen within(canvas); // Error! };环境硬性要求Node.js 20、TypeScript 4.9React Native 项目使用.rnstorybook目录而非.storybook。2.4 文档工作流指引的注入点模板第 6 行的{{DOCS_WORKFLOW_GUIDANCE}}占位符对应一段设计系统优先规则启用文档工具集时Agent 在创建或修改任何 UI 之前必须先调用docs.list查看设计系统已提供的组件——基于现有组件构建而非重复造轮子——再对要使用的每个组件调用docs.show获取真实 props 与用法示例应通过文档工具而非阅读node_modules里的库源码/类型定义来回答 props/用法问题Never assume or invent props绝不臆造 props。未启用文档工具集时该段落整体置空。三、渲染管线占位符如何被项目配置填充build-story-instructions.ts 是模板的编译器函数签名为export type StoryInstructionsInputs { transport: SkillTransport; // mcp | cli framework: string; // 框架包名 renderer?: string; // 渲染器包名缺省时按 frameworkToRendererMap 解析 changeDetectionEnabled: boolean; // features.changeDetection 是否开启 reviewEnabled: boolean; // experimental review 是否开启 testSupported: boolean; // 是否支持 story 测试 a11yEnabled: boolean; // a11y addon 是否启用 docsEnabled: boolean; // docs 工具集是否可用 };占位符替换逻辑逐一对应模板let uiInstructions storyInstructionsTemplate .replace({{FRAMEWORK}}, framework) .replace({{RENDERER}}, resolvedRenderer) .replace(\n{{DOCS_WORKFLOW_GUIDANCE}}, docsEnabled ? docsWorkflowGuidance : ) .replace({{STORY_LINKING_WORKFLOW}}, storyLinkingWorkflow) .replace({{FINAL_LINKS_GUIDANCE}}, getFinalLinksGuidance(transport, reviewEnabled)) .replace({{PREVIEW_STORIES}}, ref(stories.preview)) .replace({{CHANGED_STORY_FALLBACK_LINK_GUIDANCE}}, changedStoryFallbackLinkGuidance);其中ref由getToolName({ transport })生成保证工具名在 MCP如stories-preview类工具与 CLI 两种词汇体系下各自正确。3.1 链接工作流随 changeDetection / review 状态切换{{STORY_LINKING_WORKFLOW}}有三级降级策略体现了模板对三种能力组合的适配能力组合渲染后的工作流changeDetectionEnabled reviewEnabled修改组件/Story 后调用stories.changed发现受影响的 StoryStory ID 必须来自该调用共享基础设施变更可用stories.findByComponent兜底——严禁从文件名、导出名或记忆构造 ID视觉可观测的变更将发现的 ID 传入review.createstories.preview仅在迭代单个 Story 时使用changeDetectionEnabled无 review先调stories.changed再用结果中选取的storyId调stories.preview均未开启修改 UI 后直接调stories.preview并分享最相关的链接兜底链接指引{{CHANGED_STORY_FALLBACK_LINK_GUIDANCE}}同理开启变更检测时若未把所有变更 Story 都传入 preview需附上/?statusesaffected;modified;new这条 Storybook 兜底链接让用户能看到完整变更列表未开启时仅提示可能还存在其他相关 Story。3.2 最终回复的链接呈现规则{{FINAL_LINKS_GUIDANCE}}来自 build-server-instructions.ts 导出的getFinalLinksGuidance按reviewToolAvailable二选一review 可用最终回复只展示一组链接review 与 preview 不可并存。若已发布 review回复末尾必须是独立的 review 区块单独标题行、一句该 review 展示与本次变更最相关的少量 Story、因由 AI 整理结果可能不准确或不完整的说明、 前缀的 review 页 markdown 链接其后不得再有任何内容也不得再罗列单条 Story/preview URL视觉可观测的变更在 review 发布前不算完成。仅在变更无可视影响时才可改用 preview URL。review 不可用最终回复包含所有返回的 preview URL顺序一致先变更兜底链接、再具体 preview URL。模板中向{{PREVIEW_STORIES}}最多传 5 个最相关 Story ID、并原样包含该调用返回的全部 URL以及修改 UI 组件后必须搜索相关 Story 并再次提供链接——即使会话中已经链接过也必须重新提供链接等条目共同构成 Agent 交付环节的防漏机制。3.3 测试与 a11y 指令的条件追加testSupported为真时渲染器会在模板末尾追加两块内容story-testing-instructions.md要求每次组件或 Story 变更后运行 Story 测试工具且这是运行 Story 测试的唯一方式——绝不能用npm run test:stories等 package.json 脚本替代工作流为变更 → 用相关 Story 聚焦运行 → 失败则修复重跑 → 直到全部通过开发期优先聚焦运行传stories参数交付前/大范围重构后跑全量省略stories参数。a11y-instructions.md仅当a11yEnabled为真时追加且测试指令中的修复提示会带上 (see a11y guidelines below) 后缀。3.4 测试佐证渲染行为如何被锁定build-story-instructions.test.ts 与 skill-refs.test.ts 对渲染管线做了契约级验证例如MCP 传输下write-story技能的交叉引用渲染为冻结工具名get-storybook-story-instructionsCLI 传输下渲染为npx storybook skills get write-story框架回退行为传入未知框架如storybook/who-knows时渲染器占位符回退为框架名本身占位符解析、review 感知链接指引、测试工具集与 a11y 的开关组合均有独立用例覆盖。这些测试保证了模板占位符与build-story-instructions.ts的替换逻辑之间不会出现漂移——对维护永不截断的 Agent 指令通道而言这是关键的质量护栏。四、实践清单从模板提炼的 Agent 写 Story 流程综合模板全文与渲染逻辑一次完整的Agent 编写/修改 Story流程可以归纳为查现有能力若 docsEnabled先docs.list再docs.show基于现有设计系统组件构建不臆造 props按九条变更点写代码框架包导入Meta/StoryObj、storybook/test导入测试工具、initialGlobals、tags: [autodocs]、preview 中sb.mock注册相对路径带扩展名、Story 内mocked()覆盖按七项标准完善 Story状态全覆盖、确定性数据、play function 断言可见结果、role/label 查询、场景化命名、最小化正确操作画布直接用canvas查询需要 DOM 操作时用within(canvasElement)禁用within(canvas)运行验证每次变更后运行 Story 测试工具直至全绿聚焦运行 交付前全量运行交付链接按变更检测能力选择stories.changed→review.create/stories.preview链路遵守最终回复链接呈现规则并在后续会话中重复提供 Story 链接。五、小结storybook-story-instructions.md 不是一份静态文档而是 Storybook 9 AI 技能体系的故事编写宪法它以模板占位符与项目运行时配置框架、变更检测、review、测试、a11y、docs 六项开关解耦经 build-story-instructions.ts 渲染后经 MCP 工具get-storybook-story-instructions或npx storybook skills get write-story双通道下发。模板本身承载了 Agent 写 Story 的完整方法论与 Storybook 9 的破坏性变更清单而渲染管线确保每个项目拿到的是贴合自身能力矩阵的指令版本——这正是该文件在仓库中被大量 eval 用例如 804-write-story-for-existing-component反复引用的原因它是 Agent 行为一致性的锚点。【免费下载链接】storybookStorybook is the industry standard workshop for building, documenting, and testing UI components in isolation项目地址: https://gitcode.com/GitHub_Trending/st/storybook创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表