mcpField
U
ui-kit-from-code

ui-kit-from-code

github.com/rheinmir设计与 UI1038 次安装2 周前更新
代码仓库

关于 ui-kit-from-code

ui-kit-from-code 可将项目现有的设计令牌和组件整理为独立 HTML 参考套件,供设计师、开发者和 Agent 查阅复用。它通过组件覆盖检查和 Playwright 验证提供依据,不修改项目组件代码。

主要功能

  1. 01从项目代码提取令牌
  2. 02生成独立 HTML 参考页
  3. 03展示组件变体与交互状态
  4. 04支持主题切换与复制
  5. 05检查清单覆盖和页面布局

适用场景

  1. 01制作可复用的设计系统参考页
  2. 02检查组件变体和交互状态
  3. 03通过单个文件分享项目令牌与标记

安装

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

$npx skills add https://github.com/rheinmir/setup --skill ui-kit-from-code

安装后在 Claude Code 中输入/ui-kit-from-code确认已加载。

包含的文件

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

references/
discover.mjs
sync-kit.py
ui-kit-reference.html

详细介绍

技能:ui-kit-from-code

内容

目的与背景
  • 目的: 构建一个独立的 HTML 文件,让用户(设计师、开发者、Agent)查阅并复用项目的真实设计系统,作为 Figma UI kit:查看所有 token 和组件、即时切换主题、直接复制 token 或标记以供使用。
  • 触发场景:“把它拆出来做成 UI kit”“用 HTML 做 Figma UI kit”“设计系统参考页面”“可复用的组件库”。通常出现在项目已有稳定的 token 和组件,但还没有页面将它们汇总起来时。
  • **非目标:**创作新系统或调整美学风格(→ hallmark);完整克隆页面以便重新运行(→ extract-site / web-clone);导出真正的 Figma 文件、Storybook 或 npm package;修改项目的组件代码。
心智模型
nguồn token (TS/CSS/Tailwind/Compose…) ──chạy thật──▶ JSON token ──▶ CSS vars --<ns>-<role> + --k
component trong code (kích thước, variant, tên kind) ──đọc──▶ class .<ns>-* chỉ dựa vào vars
URL gốc ──discover.mjs (link BFS · mở phần ẩn · chữ ký · bão hoà)──▶ inventory.json + crops ──▶ danh mục phải dựng
kit.html + inventory.json ──--coverage──▶ phủ 100% (data-sig / ui-kit-skip)
                                   └──▶ ui-kit.html (7 phần bắt buộc) ──Playwright──▶ bằng chứng

Kit 是代码中系统的可验证副本:每种颜色和尺寸都能追溯到仓库中的某个常量或函数。如果代码没有明确说明、必须按规范绘制,就必须注明(RULE-04)。

输入与输出约定
字段必填?含义
输入token 来源是生成颜色、字体、形状和尺寸的文件/函数(例如 lib/tokens.ts → paletteOf)
输入组件目录是类型名称(kind/component name)+ 应用中的分组方式(palette、sidebar、docs)
输入目标平台是mobile / desktop / 两者,附真实视口尺寸
输出docs/ui-kit.html(或用户选择的路径)是1 个文件,可通过 file:// 打开,包含下方全部 7 个部分
输出来源报告是说明哪些部分来自代码,哪些部分按规范绘制
输出Playwright 证据是0 个 JS 错误,390px 下 scrollWidth - innerWidth = 0,亮色 + 暗色 + 屏幕示例截图
输出kit 仓库上的版本是(UI_KIT_SYNC=0 除外)PRIVATE 仓库 Rheinmir/ui-kits(W09)中的 <id>/vN/index.html + manifest.json + registry.json 条目
规则与能力
  • RULE-01(MUST):颜色和尺寸必须通过运行项目的代码获取(临时测试运行器/脚本,导出后删除),不得手动输入十六进制值。对于只能读取而无法运行的代码(CSS 变量、JSON),则解析文件。
  • RULE-02(MUST):组件类只能引用 CSS 变量(--<ns>-<role>、--k);组件 CSS 中不得出现零散的十六进制值或 rgb 值。这样,:root 块和 CSS .<ns>-* 就能直接移到其他项目中运行。
  • RULE-03(MUST):每张组件卡片都必须准确记录代码中的名称(kind/component name + 主要字段)和代码使用的尺寸(dp/px)。
  • RULE-04(MUST):在报告中(必要时也在卡片备注中)说明所有按规范绘制或经过简化的部分(例如,形变动画仅旋转);不得将其呈现为 1:1 复刻。
  • RULE-05(MUST):必须包含以下 7 个结构部分;缺少任何部分时,必须在报告中说明原因(例如,应用没有桌面端)。
  • RULE-06(MUST):文件必须自包含:字体仅来自 Google Fonts,JS/CSS 内联,不进行构建,也不从外部获取数据。
  • RULE-08(MUST):**不能止步于框架。**组件清单必须来自 W01b 探索过程(沿链接浏览、点击展开隐藏内容,并在结果趋于饱和时停止),不能只根据几个已知页面/文件整理。inventory.json 中的每个 pattern 都必须在 kit 中有一张带有 data-sig="<sig>" 的卡片,或通过 <meta name="ui-kit-skip" content="<sig>:<理由>;…"> 说明排除原因。门禁:node references/discover.mjs --coverage inventory.json kit.html 返回码为 0。
  • RULE-10(MUST):**组件不能只有默认状态。**W01b 测得的每种状态(hover、focus-visible、active、selected)都必须呈现在 kit 中:卡片应展示对应状态的变体(使用 is-hover / is-focus / is-active / is-on 类,准确复现网站的 :hover 等规则),并带有 data-sig-state="<sig>:<state>"。或者通过 ui-kit-skip "<sig>:<state>:原因" 说明排除原因。如果焦点状态仅为浏览器的 outline:auto(ua: true),kit 必须明确注明“焦点使用浏览器默认样式,网站没有单独设置样式”。--coverage 门禁也会统计状态。
  • RULE-11(MUST):遵守 robots.txt 和网站条款。discover.mjs 会在扫描前读取 /robots.txt。如果 User-agent: * 禁止起始路径,或有禁止自动采集的说明(例如 facebook.com),则返回码为 3 并停止;不要自行添加 --i-have-permission。只有用户确认拥有许可时才能使用此标志。改为建议使用 B05:由用户自行保存页面。
  • RULE-09(MUST):如果来源是他人网站,不得将其图片、logo、SVG 字标或受版权保护的内容嵌入 kit;应改用明确标注“图片 …”的占位块。Kit 可以自动同步到 PRIVATE 仓库(W09);如需将其分享至该仓库之外(公开链接、托管),请先征求同意(B03)。
  • RULE-12(MUST):只同步已通过检查的 kit(W05b + W06 为绿色),并且只能同步到 PRIVATE 仓库——sync-kit.py 会自动检查 visibility,并拒绝 PUBLIC 仓库(GH#187)。版本号只能递增:不得覆盖或删除旧的 vN。
  • RULE-07(SHOULD):制作时将示例文件 references/ui-kit-reference.html 放在旁边;复用其框架、页面外壳 CSS 和控制脚本,只替换 token、组件和示例屏幕。
  • Capabilities:读取代码库;运行项目的测试运行器/脚本;编写 1 个 HTML 文件;运行 Playwright(参见 /playwright-verify)。
每个部分的必备结构

严格按照 references/ui-kit-reference.html 中的顺序:

#部分必须包含示例文件中的对应项
1控制栏(sticky)选择调色板(如果应用有多个)· 浅色/深色 · 形状比例(如果应用有)· 为当前选择的 :root 块提供「Copy CSS token」按钮;使用 localStorage 记住选择(用 try/catch 包裹);首次使用时遵循 prefers-color-scheme.bar · #swatches #mode #shape #copy-tokens
2目录(侧边栏,小于 900px 时隐藏)按基础样式 / 组件 / 示例分组;自动高亮当前查看的项目(IntersectionObserver).side
3简介eyebrow 用于指明源文件(<file token> → <file kit>)· h1 · 一段说明 kit 的来源及复用方式 · 列出重要布局常量的「facts」条.intro .facts
4基础样式(a) 颜色: 所有角色、文字颜色为正确配对的 on* 色块、点击即可复制 hex · (b) 文字: 字号比例,包含名称 + size/line-height/weight · (c) 形状: 圆角比例乘以 --k · (d) 布局与尺寸: 主要组件尺寸比例表 + 框架/边距/间距常量表#color #type #shape #layout
5组件按应用现有分组方式组织(如操作 · 导航 · 内容容器 · 输入 · 反馈);每张 .spec 卡片 = 标题栏(可读名称 + 代码名称标签 + 尺寸)→ .stage 展示所有重要变体/尺寸/状态 → 页脚(备注 + 自动附加的 Copy HTML 按钮);卡片带有其覆盖的 pattern 的 data-sig(RULE-08)。inventory 中 pattern 较多的分组应按 pattern 拆分卡片,不要合并成一张通用卡片#actions #navigation #containment #inputs #feedback
6示例屏幕至少包含 1 个 移动端屏幕和 1 个 桌面端屏幕(应用支持时),使用应用的正确框架尺寸,并通过 zoom 缩小;使用第 5 部分中的组件类,按应用的布局规则组合(如移动端底部导航 → 桌面端导航栏 + 列表-详情);在框架下方注明所用组件#screens .phone .desk
7脚本以 ROLES + PALETTES[key].light/dark 形式嵌入 token 表,由 dump 生成 · apply() 将 CSS var 写入 :root · 根据数据渲染色块 / 字号比例 / 形状比例 · 绑定复制按钮 · 显示复制成功 toast(剪贴板受阻时提示手动复制)文件末尾的 <script>

整个页面通用要求:页面外壳使用 kit 自身的 token(页面换主题时组件也随之变化);prefers-reduced-motion 关闭动画;:focus-visible 清晰可见;图标按钮带有 aria-label;在 390px 宽的移动端不出现横向溢出(表格/示例屏幕放在 overflow-x:auto 容器中)。

故障边界
  • 找不到 token 来源(组件中散落着硬编码颜色)→ partial:通过 grep 汇总实际使用的颜色,明确写出“没有 token 来源,颜色根据组件推断”,建议拆分 token(单独处理)。
  • 网站在独立容器中滚动(body 高度正好为 1 屏)→ fullPage 只会截取 1 屏;discover.mjs 会在截图前自动打开容器,自行编写的脚本也必须这样做。
  • 状态仅在 JS 运行时出现(点击打开的菜单、延迟出现的 tooltip、进入动画)→ 纯 :hover CSS 状态可测量,但依赖 JS 的状态可能会漏掉;W01c 查看 *-hover.png 裁剪图后自行补充。按住(active)状态通过 mouse.down 测量 → 将鼠标拖到外部 → mouse.up,因此不会触发链接。无法测量时,请在报告中明确说明。
  • 页面禁用 JS(B05):JS 添加的状态(例如 FDS Facebook 的 hover/pressed 覆盖层)无法测量。根据相应 token(--hover-overlay、--press-overlay)还原,并明确写出“根据 token 还原,未测量”。页面很重(feed 有 3000+ 个元素)时,需要提高 --page-timeout。
  • 探索达到页面上限(stoppedBy: page-budget),但最后一个页面仍出现新模式 → 告知用户,建议提高 --pages 或缩小 --include 范围,不要将 kit 视为完整。
  • Token 只能在繁重的运行时环境中运行(需要 DB/app server)→ 使用 Playwright 从运行中的应用导出(对 :root 调用 getComputedStyle),并说明获取方式。
  • 项目只有一个平台 → 第 6 部分只展示该平台的屏幕,并说明原因。
  • Playwright 报告 JS 错误或经过 3 轮修复后仍然出现横向溢出 → 停止并报告剩余错误。
  • W09 同步时遇到网络错误/没有推送权限/仓库不是 PRIVATE → 脚本输出“尚未同步,原因 …”,rc 0;本地 kit 仍是有效结果,请在 W08 中说明原因。

操作方式

主要工作流
步骤类型输入操作输出/退出失败/后续
W01判断代码库查找 token 来源、组件目录 + 分组、移动端/桌面端框架尺寸、schema 文档(如有)file:line 锚点列表没有 token → 部分完成(见 Failure)
W01b确定性原始 URL(开发中的 app 或网站)探索循环:NODE_PATH=$(npm root -g) node references/discover.mjs <url> --out <scratch>/disc --pages 32 --saturate 4(需要全局安装 Playwright;每页约 40 秒,在后台运行)(BFS 遍历同源链接,滚动所有内部容器,点击展开 accordion/tab/details;签名 = 类型 + 样式 + 子项形状,去重;对于可点击模式,还通过 CDP CSS.forcePseudoState 强制触发 HOVER / ACTIVE / FOCUS-VISIBLE(类似 DevTools 的“Force state”:确定性,不拖放、不点击,关闭 JS 后也能运行),并根据 aria-pressed/selected/current、data-state、class is-active 合并 SELECTED 变体)inventory.json + crops/*.png + 每页截图stoppedBy: page-budget 且仍有新内容 → 增加预算(Failure)
W01c判断crops + 页面截图查看所有新 crop 和整页截图;将模式归组为 kit,并把分类器遗漏的模式(例如梯形 tab、流程图)记入待实现清单模式 → 分组 → kit 卡片表—
W02确定性token 锚点编写临时测试/脚本调用真实 token 函数,导出 JSON(所有 palette × 浅色/深色、尺寸比例)→ 删除临时文件scratchpad 中的 tokens.json运行失败 → 静态解析
W03效果JSON精简为 ROLES + PALETTES,并嵌入样板文件副本<script> 中的数据块—
W04判断组件代码重写第 4–5 部分:每个组件使用一个 .<ns>-* class,测量值取自代码;.spec 卡片包含 header/stage/footer第 4–5 部分代码中缺少测量值 → 按 spec 绘制并说明(RULE-04)
W05判断app 布局规则拼接第 6 部分:使用 W04 中的 class 构建移动端 + 桌面端屏幕第 6 部分app 仅支持一个平台 → 说明原因
W05b确定性kit + inventorynode references/discover.mjs --coverage <scratch>/disc/inventory.json <kit.html>覆盖 N/N (100%) + 状态 M/M,rc 0缺少模式 → 构建卡片;缺少 sig:state → 为卡片添加状态变体(RULE-10)或添加有理由的 ui-kit-skip;重新运行
W06确定性文件Playwright:加载页面,统计 pageerror,截取页面顶部 + 中部 + 样例屏幕;开启深色模式 + 更换 palette 后重新截图;在 viewport 390 下测量横向溢出截图 + 数值出错 → 修复,最多 3 轮
W07判断截图查看一轮截图,修复可见的布局问题(文字挤在一起、项目错位),再截图 1 次kit 完成—
W08判断结果向用户报告:文件路径、7 个部分的内容、哪些部分来自代码/按 spec 构建、W06 的证据、W09 的同步结果报告—
W09效果已通过 W05b + W06 的 kitpython3 references/sync-kit.py <kit.html> --source <仓库目录 | 原始 URL>(无法从来源推断 id 时添加 --id <id>,例如登录后的 app)。Id:仓库 → 从 origin 获取 <owner>-<repo>(没有 remote → <目录>-local);URL → 去掉 www. 的 host,并将点替换为连字符。sha256 哈希忽略 meta ui-kit-id;与最新版本相同 → “与 vN 相同”,不提交。不同 → vN+1 + latest/,推送;若被拒绝则拉取后重新计算,最多 3 次。UI_KIT_SYNC=0 跳过;UI_KIT_SYNC_REPO 更改仓库✓ <id>: vN → <link> 或 = 不变出错 → “尚未同步,原因”,rc 0(Failure)

**token 导出示例(vitest,TS):**创建 lib/zz-kit-dump.test.ts,调用 token 函数,然后执行 writeFileSync(<scratchpad>/tokens.json, …),运行 npx vitest run lib/zz-kit-dump.test.ts,再执行 rm 删除文件。不要让临时文件出现在项目 diff 中。

**Playwright 检查示例:**如 /playwright-verify:chromium.launch() → goto(file://…/ui-kit.html) → page.on("pageerror") → screenshot → click('#mode button[data-v="dark"]') → 在 390×844 页面上测量 document.documentElement.scrollWidth - innerWidth。

分支
ID类型条件行为跳过/失败汇合
B01conditional_requiredtoken 是 CSS vars/Tailwind config/JSON(不是函数)静态解析,不运行(W02)—W03
B02conditional_requiredapp 有面向 agent 的 schema 文档(例如 agent.md)“代码中的名称”标签使用 schema 中准确的字段名,示例屏幕遵循该文档中的规则没有 → 使用 component 名称W04
B04conditional_required来源是正在运行的 site URL(没有代码)将 W02 替换为 Playwright:读取 :root/.dark 中的 CSS vars 和实际元素的 getComputedStyle;将 lab()/oklch() 颜色转换为 hex;应用 RULE-09有代码 → 跳过W03
B05conditional_requiredsite 禁止 crawler(RULE-11)或界面位于登录后user 将页面自行保存(“Webpage, Complete”)到一个文件夹 → python3 -m http.server 8765 --bind 127.0.0.1 → discover.mjs http://127.0.0.1:8765/<file>.html --offline --no-js --page-timeout 1500(阻止所有外部请求,关闭 JS,避免脚本自动回连 site)。保存的页面包含个人数据:kit 仅提取样式/结构,所有名称/图片/内容均替换为示例,交付前用 grep 检查真实名称site 允许 crawl → 使用常规 W01bW01c
B03user_optionaluser 希望将分享链接发布到 kit private 仓库之外将文件上传到 user 选择的 Artifact/hosting;文件仍保留在 repo 中默认:本地文件 + kit private 仓库(W09)W08
验证与停止

机器检查:W09 的确定性测试 python3 -m pytest harness/tests/test_ui_kit_sync.py(id、hash、版本号、v1 不变);W05b 覆盖率门禁 rc 0(每个 pattern 都有 data-sig 或 ui-kit-skip);W06 必须确保 pageerror = 0 且在 390px 下水平溢出 = 0。人工检查:根据结构表确认 7 个部分齐全;对比明暗模式截图;测试 Copy CSS token 按钮和 1 个 Copy HTML 按钮。W06 最多修改 3 轮,W07 只重新截图一次。

示例
  • **正向:**m3e-canvas(Next.js,Material 3 Expressive 编辑器)。将 paletteOf() 的 vitest 输出为 7 个调色板 × 亮色/暗色;工具包包含 25 个颜色角色、15 种字体样式、3 种形状级别、约 30 个组件,分为 5 组,类似应用中的 Parts 表;移动端屏幕为 412×892(列表 + 详情),桌面端为 1280×800(导航栏 + 列表-详情);Playwright 0 个错误,390px 下无溢出。主要产物是 references/ui-kit-reference.html。
  • **正向(URL):**drafted.ai。首次只扫描了 3 个已知页面,因此工具包只有基本框架。从 /learn/ai-for-homebuyers 运行 W01b,使用 --pages 32 --saturate 4:discover.mjs 遍历了 32 个页面(learn、use-cases、房屋示例列表页、FAQ、新闻、招聘、引导流程),收集 171 个模式,连续 4 页没有新内容后停止(约 40 秒/页)。W05b 首次报告 覆盖 62/171 (36%)。随后补建房屋示例列表、文章与区块等分组,根据清单生成实际使用的字体表,并记录 22 个 ui-kit-skip(图片、第三方嵌入内容、页面框架),检查关卡报告 覆盖 171/171 (100%)。W01c 还发现一个分类器遗漏的模式:用 SVG 绘制的梯形标签页。 第 3 轮增加了状态测量:175 个模式、104 种状态(44 个 hover、56 个 focus、1 个 active、3 对 selected)。首次结果为 状态 0/104。添加 23 条状态带和“Focus · 2 种”卡片后,检查关卡报告 175/175 + 104/104。测量还修正了此前 6 条错误猜测的 hover 规则(例如,选择卡片 hover 时变为 stone-500,而不是 stone-900),并显示 44/56 个 focus 状态只是浏览器默认轮廓。
  • **正向(B05,网站禁止爬虫):**facebook.com。robots.txt 禁止自动采集,因此 discover.mjs 以 rc 3 停止,Agent 询问用户。用户保存 News Feed(6.4 MB + 252 个资源),离线运行并关闭 JS(阻止 49 个外部请求)。从已保存的 CSS 中获取了 .__fb-light-mode 和 .__fb-dark-mode 的 579 个 FDS 变量、78 个模式、5 种可测量状态(FAB hover 时阴影改变,story active 时为 scale(.98),链接 hover 时显示下划线)。按钮的 hover/pressed 状态根据 --hover-overlay/--press-overlay 构建。工具包包含 27 张卡片、66 个颜色角色;检查关卡结果为 78/78 + 5/5;grep 未发现真实姓名;0 个外部请求。
  • **边界情况/失败:**React 仓库只有分散在 40 个 .module.css 文件中的十六进制颜色,没有 token → 部分完成:grep 找到 18 个实际使用的颜色,工具包标注“颜色根据组件推断”,并建议先拆分 token,再构建完整工具包。

评论

支持 Markdown