mcpField
D
directions-lab

directions-lab

github.com/paperclipai其他109.4k12 次安装今天更新
代码仓库

关于 directions-lab

directions-lab 是用于在代码库中搭建设计探索页面的 skill,生成 Today 与多个方向的对照视图,并提供统一控件、注册表配置和 Storybook 条目。

主要功能

  1. 01搭建 Vite 设计方向页面
  2. 02对照 Today 与两个或三个方向
  3. 03通过注册表配置方向和界面
  4. 04生成 Storybook 提案故事
  5. 05运行脚手架检查与测试

适用场景

  1. 01为产品功能创建设计探索
  2. 02将备选设计与已发布组件对照
  3. 03向 Storybook 设计目录添加提案

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/paperclipai/paperclip --skill directions-lab

安装后在 Claude Code 中输入/directions-lab确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

agents/
openai.yaml
assets/
PRECEDENT
assets/motion/
v1-mvp-motion.css
assets/templates/
api-routes.ts.mjs
api-stub.ts.mjs
build-info.ts.mjs
define-lab.ts.mjs
entry.html.mjs
fixtures.ts.mjs
kit.ts.mjs
lab-state.ts.mjs
lab.css.mjs
launch-entries.json.mjs
main.tsx.mjs
providers.tsx.mjs
registry.ts.mjs
shot.cjs.mjs
assets/templates/direction/
index.tsx.mjs
MotionSpecimen.tsx.mjs
SlotBody.tsx.mjs
tokens.css.mjs
assets/templates/frames/
AppShell.tsx.mjs
Board.tsx.mjs
LabToolbar.tsx.mjs
Slot.tsx.mjs
SurfaceFrame.tsx.mjs
SurfaceView.tsx.mjs
assets/templates/stories/
compare.stories.tsx.mjs
assets/templates/tests/
api-stub.test.ts.mjs
lab-state.test.ts.mjs

详细介绍

方向实验室

方向实验室是本仓库进行设计探索的方式:一个页面、一个功能、Today 加上两个或三个方向、该功能出现的每个界面,以及每次都相同的控件,这样共享链接对所有人来说显示一致。artifact 方向实验室(ui/src/artifact-directions)是先例,并保持为冻结的参考;此技能会以相同的结构生成新的实验室,无需手动重画基础设施。

要创建的内容

  • 页面。 ui/<slug>-directions.html 加上 ui/src/<slug>-directions/,这是一个没有后端的 Vite 第二入口。所有状态都保存在 URL 中(?d=&s=&theme=&chrome=&anim=,提案调色板则加上 proposal=1)。注册表模块是方向 ID、数字键、标签、界面、默认视图和故事 ID 的唯一数据源;工具栏、键盘、概览板和截图脚本会在运行时读取它,而 add-direction 会同步更新故事中各方向的导出,因此添加一个方向只需添加一条注册表记录和一个目录。
  • 工具栏。 第 1 行是方向行:先显示编号方向,再将 0.Today 放在最后,以分段控件呈现;Theme 和 Animation 靠右对齐。第 2 行是界面行:Overview 加上每个界面的一个标签页。只有在实验室脚手架包含多个界面时才会写入第 2 行(单界面实验室后续添加界面时,需要手动添加第 2 行,见 references/lab-anatomy.md 第 8 节);只有一个界面时,键盘图例会并入第 1 行。页眉中不得放入其他内容。
  • Today。 始终存在,始终为 0.Today,始终通过小型适配器和 fetch 存根,将已发布组件挂载到实验室的固定数据上。它是评判每个方向的基准,因此绝不重绘。
  • 方向。 两个或三个,编号排列;每个都是自包含的套件目录,并拥有自己的作用域 tokens.css。每个方向都必须原样包含 V1 MVP 动效代码块,并附带一个证明该代码块的测试,这样悬停效果在各实验室中都保持一致。动手前请阅读 references/motion-spec.md。
  • 目录条目。 在 ui/storybook/stories/design-proposals/ 下放置一个带稳定 ID 的故事文件,并将其编入提案目录。design-proposals Storybook 正在成为设计系统的规范目录;实验室从首次提交起就应在其中可见。

硬性规则,因为仓库的检查会强制执行,评审者也会据此检查: 提交的任何内容中都不得包含代码注释;实验室中不得有 600 行或更多的文件(check 会在达到 600 行时拒绝);不得修改 package.json 脚本;不得更改 lockfile;不得在仓库中加入截图或生成的目录文件。

开始之前

从仓库根目录在自己的分支上运行(分支名为 claude/<slug>-directions,基于 origin/master)。检查 ui/node_modules/.bin/vite 是否存在;如果不存在,运行 pnpm install --frozen-lockfile。然后运行生成器自己的测试:

node --test .agents/skills/directions-lab/scripts/scaffold.test.mjs

这里失败通常说明模板或动效资源已偏离先例(ui/src/artifact-directions/directions/d5-v1-mvp/tokens.css);其中有两个用例还会读取实际功能映射和目录脚本,因此功能映射中的行或目录消息发生变化时,也会在这里显示。先修复生成器,再搭建脚手架;基于过时模板构建的实验室会在之后失败,而且失败的表现看起来像是你画错了。

阅读需求说明,再深入了解主题

从 Tonio 的说明中提取四项内容:主题(其 slug 和标题)、出现的位置(每个位置对应一个界面)、明确给出的方向数量或名称,以及任何标志或组件名称。然后,在提出任何问题前先查看代码:

rg -l "<Subject>" ui/src/components ui/src/pages
rg -n "<subject word>" maps/feature-map/*.md

第一条 grep 会给出组件文件和标志钩子(use<Feature>Enabled),并通过追踪 useQuery/queryFn 到 ui/src/api/*,找到 Today 必须响应的 /api/ 路由。第二条会给出故事引用的能力 ID。通过这番了解,才能提出针对具体界面的提问,而不是泛泛而谈。完整的提取和推导表见 references/questions-and-defaults.md。

一次询问

最多提出两个问题,并在一次 AskUserQuestion 调用中询问;简述中已回答的问题则跳过:

  1. 需要多少个方向? 选项为 2 和 3。在问题中说明,三个未命名方向会依次搭建为 1.Refine(调整 token 和间距,结构不变)、2.Rework(使用新组件,布局不变)和 3.Rethink(使用新布局);两个方向则搭建为 1.Refine 和 2.Rethink,之后会重命名。简述已说明数量或命名方向时跳过。
  2. 需要哪些界面? 从 grep 找到的使用位置中多选,并提供“仅一个位置”选项。选择两个或更多位置时才会生成界面行。简述已命名位置时跳过。

绝不要询问主题、动画、Today、端口、slug 或落地视图;这些由技能固定。当无法提出问题时(无头运行),先写下这句话,然后继续:“由于无法提问,默认使用三个方向和一个界面();之后可通过 scaffold.mjs add-direction 更改。”

说明推导结果,然后搭建

运行生成器前,在回复中说明所有推导出的值:slug 和标题、每个界面的 id:Label:width@nav 格式及宽度来源所在行、方向数量和名称、分组、能力及其 feature-map 行(或 [] 和例外说明)、flag hook,以及 Today 需要的 /api/ 路径。此时发现 slug 或能力有误,修正成本很低;等文件生成后再发现,代价就很高。然后:

node .agents/skills/directions-lab/scripts/scaffold.mjs new \
  --slug composer --title "Composer" \
  --surfaces thread:Task-thread:960@tasks,panel:Right-panel:434@tasks \
  --directions 3 --dry-run

读取计划(路径、端口、单元格、故事),移除 --dry-run 并运行。new 会在内存中渲染所有内容,拒绝使用已存在的路径,写入实验室、html 入口、Vite 配置、故事文件、两个 .claude/launch.json 条目和一行 .gitignore 内容,然后执行验证:Storybook 目录检查、实验室自身的 Vitest 文件检查,以及 Vite 构建。如有任何步骤失败,它会删除已写入的内容并还原两个共享文件,因此未完成的实验室不会导致整个仓库的 pnpm test 或 tsc -b 失败(ui/vitest.config.ts 没有 include 过滤器,而 ui/tsconfig.json 包含了整个 src)。在回复中引用 --json 输出。

--surfaces 对每个位置接收 id:Label:width@nav,其中 nav 是 shell 高亮显示的侧边栏项目(tasks、artifacts 或 other),而 width 是该位置在产品中使用的常量(参见 references/questions-and-defaults.md)。可用标志:已指定名称时使用 --names a,b,c;使用 --group Components|Pages|Layouts|Patterns(grep 命中 ui/src/components 时使用 Components);使用 --capabilities area/key,...(根据 maps/feature-map 验证;省略时使用 [] 并附上例外说明);使用 --company name:PREFIX(默认值为 acmehats:ACM);使用 --landing auto|all|today|<id>;使用 --ports dev,preview(生成器会选择空闲端口);使用 --keep-on-failure 检查搭建失败的实验室。

查看效果

启动生成器添加的 dev 入口,运行 preview_start {name: "<slug>-directions-dev"},并打开三个 URL:/(落地页)、/?d=today&s=<first surface> 和 /?d=<first direction id>&s=<first surface>(方向未命名时使用 d1-refine)。确认 document.documentElement.dataset.labAnim === "1",将鼠标悬停在一个动效样例上,观察正面升起、两页翻转;按下 a,再次悬停,确认只有填充发生变化。检查控制台中是否有 [<slug>-directions] unhandled 行:每一行都代表 Today 需要的一个路由。概览板和截图脚本都无法呈现运动效果(iframe 不接收指针;静态图会启用减少动态效果;--hover 只会记录一帧悬停画面,而不是过渡过程),因此只能通过这种方式验证过渡效果。

提交脚手架,然后绘制

先将未经修改的脚手架提交为 feat(ui): scaffold the <title> directions lab。这样,审查者就能将重绘作为独立差异查看,而不是让它埋在基础设施代码里。按以下顺序绘制;references/drawing-phases.md 中列出了每个阶段的完成标准:

  1. 框架。 将每个 data-lab-stub="frame-<surface>" 区域替换为该位置周围的产品界面框架:复制产品的类名字符串,固定注册表宽度,复用展示用基础组件,不要让任何内容在内部滚动。参考框架展示了具体做法(ThreadFrame、PanelFrame、GalleryFrame、AppShell)。
  2. 固定数据和 Today。 在 kit.ts 中重新定义各位置的数据类型,使其符合每个位置接收的 props;填充 fixtures.ts;通过 adapters.ts,在 directions/today/<Pascal>Body.tsx 中挂载随产品发布的组件(使用位置 ID 的 PascalCase,因此 thread 对应 ThreadBody.tsx);并在 api-routes.ts 的 registerFeatureRoutes() 中,仅注册它实际获取数据所需的路由。当 Today 使用相同数据后与产品一致,且测试通过真实组件运行时,此阶段即完成。
  3. 方向稿。 每次处理一个方向:将动态效果示例替换为绘图,保留钩子名称(每个处理分支都要有 data-front,data-rotate 和 data-spread 要包含行内基础角度),将每个原始值放入该方向的 tokens.css(浅色基础值、.dark 覆盖值),并保持动态效果区块不变。每个阶段完成后运行 scaffold.mjs check --slug <slug>。

阶段 2 必须先于阶段 3,因为第 2 阶段会改变插槽 props 的结构,而所有 kit 都遵循该类型。

截图

node ui/src/<slug>-directions/shot.cjs --port <dev> --d all --out <scratch dir>

截图应为 1440×900、DPR 2 下的静止状态,包含两种主题;将 PNG 附加到 PR,绝不要放入代码仓库。--hover 会从允许运行动效的第二个浏览器上下文中,为每个方向额外生成一组静止/悬停截图;要判断动态效果本身,仍只能在开启 Animation 切换开关的浏览器面板中查看。

交接

node .agents/skills/directions-lab/scripts/scaffold.mjs check --slug <slug> --strict --run

--strict 会拒绝任何残留的 data-lab-stub 标记;--run 会运行实验室测试、目录检查、令牌门禁、实验室的 Vite 构建以及 cd ui && pnpm typecheck,遇到首个失败即停止,并输出 ## Verification 区块,其中 Not run: 行会列出仍需手动运行的项目(pnpm build-storybook、全仓库类型检查);--json 会以数据形式返回相同结果,并将这些项目列在 notRun 下。创建 PR 时,.github/PULL_REQUEST_TEMPLATE.md 的每个部分都要填写;使用关联问题路径 B,填写三个功能请求标签、故事 ID、启动条目,以及已部署时的 Vercel 别名。在 PR 正文中以文本形式提供 DESIGN.md 目录行;不要在实验室 PR 中应用它。

如果技能本身包含在你的差异中,请强制添加:/.agents/ 被 git 忽略,而仓库中已跟踪的技能是通过 git add -f 添加的。

Storybook 和 design 目录

new 会写入 ui/storybook/stories/design-proposals/<slug>-directions.stories.tsx, 其中包含 meta id design-<slug>-directions、标题 Design proposals/<Group>/<Title> directions/Compare、字面量 parameters.paperclip 块(status: "proposed"、home: "design-proposals"、implementation: "prototype"、 boundary: "fixtures"、capabilities、exception、notes),以及 Compare、 Today、每个方向各一个故事,还有 TodayProductionPalette(装饰器会用提案调色板为 整个 iframe 设置主题;此项会退出主题设置,因此 Today 显示的是已发布版本)。页面本身 默认渲染生产调色板;?proposal=1 会为其套上提案主题,以便与入口并排比较。 catalog 脚本会在 Storybook 启动时、执行 cd ui && pnpm typecheck 时以及 CI 中验证所有内容。

方向经历的生命周期,以及每个阶段需要手动编辑的内容,见 references/lifecycle.md:proposed(new 写入的内容)、adopted(产品代码置于实验性设置 之后,并带有功能主页故事)、current(移除标记)、historical(退役并注明 replacement,移出 proposals 文件夹但保留其 id)。目前 catalog 会强制 proposals 文件夹中的所有条目保持 proposed;允许目录收录 current 条目的治理变更已整理成可直接粘贴的 差异,见 references/canonical-directory.md。只有 Tonio 同意后,才单独提交一次该变更的 PR。

后续请求

  • 添加方向:scaffold.mjs add-direction --slug <slug> --name <Name> (下一个数字、registry 条目、包含 motion 块和样例的 kit 目录、故事的 D<N> 导出,然后执行 check,失败时回滚)。 工具栏图例会在运行时跟随 registry。生成器拒绝添加第四个方向,除非使用 --force-count;该参数还会在 registry 中记录 allowMore;故事描述中的“1–N”句子是唯一 需要手动更新的内容。phase 2 在 kit.ts 中重新定义 slot props 的类型后, add-direction 会拒绝执行并打印手动操作步骤,因为生成的 kit 将无法适配新的 props。
  • 列出实验室:scaffold.mjs list。
  • 重命名方向、添加界面,或让方向进入生命周期的下一阶段:按照 references/lab-anatomy.md 第 5 和第 8 节以及 references/lifecycle.md 手动操作。
  • 发布:使用 <SLUG>_DIRECTIONS_OUT_DIR=<dir>/paperclip-<slug>-directions 构建, 从输出中移除 sw.js,然后在其父目录执行 vercel deploy <that dir> --prod --yes; basename 会作为项目名称,alias 则是公开 URL。 详情见 references/today-fixtures-and-build.md 第 11 节。

不要

  • 不要同时运行两套完整的 ui Vitest 测试套件;只运行实验室自身的文件。
  • 如果开发服务器中的单元格超过八个,不要从 d=all&s=board 启动;要显示完整看板,请使用静态启动入口(<slug>-directions)。
  • 不要照搬 artifact lab 的 html:not(.dark) token 写法;新实验室应在基础块中放置浅色值,并在 .dark [data-direction=…] 下放置深色值。
  • 不要编辑实验室中的 motion 块。是否更改 rise 或 fan 由 Tonio 决定。
  • 不要在将纳入 PR 的内容中添加注释、package.json 脚本、锁文件变更、PAP id 或 localhost URL。

维护 skill

生成器模板源自 assets/PRECEDENT 中记录的提交所采用的先例。 scripts/scaffold.test.mjs 会锁定生成结构,并断言替换后 motion 资源仍与先例中的块一致;先例变更时, 重新推导模板并更新锁定版本。references/generator.md 说明了模板约定和上下文对象。

参考资料

文件阅读时机
references/questions-and-defaults.md提问前;推导表、作为标志行的评估提示词
references/lab-anatomy.md绘制框架或更改工具栏、状态或画板时
references/today-fixtures-and-build.md挂载 Today、获取模拟数据、构建、捕获或部署时
references/motion-spec.md涉及任何悬停动效时;各方向的检查清单
references/drawing-phases.md搭建脚手架后,逐阶段阅读
references/design-proposals-storybook.md故事文件、目录门禁、主题
references/lifecycle.md采用、发布或弃用某个方向时
references/canonical-directory.md仅在 Tonio 批准治理 PR 时
references/repo-gates.mdPR 前
references/generator.md更改生成器时

评论

支持 Markdown