mcpField
U
ui-kit-from-code

ui-kit-from-code

github.com/rheinmirデザイン・UI1038 回インストール2 週間前に更新
リポジトリ

ui-kit-from-code について

ui-kit-from-codeは、プロジェクト既存のデザイントークンとコンポーネントを、単体で使えるHTMLリファレンスキットにまとめるスキルです。デザイナー、開発者、エージェント向けに、コンポーネントの網羅性と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 ファイルを作成し、デザイナー、開発者、エージェントが、Figma UI キットのようにプロジェクトの実際のデザインシステムを参照して再利用できるようにします。すべてのトークンとコンポーネントを確認でき、その場でテーマを切り替えたり、トークンやマークアップを直接コピーして使ったりできます。
  • トリガー: 「UI キットとして抽出して」「HTML で Figma UI キットを作って」「デザインシステムのリファレンスページ」「再利用できるコンポーネントギャラリー」。通常、プロジェクトのトークンとコンポーネントが安定しているものの、それらをまとめたページがまだない場合に発生します。
  • 対象外: 新しいシステムの考案や見た目の調整(→ hallmark);ページ全体を複製して再実行すること(→ extract-site / web-clone);本物の Figma ファイル、Storybook、npm パッケージの出力;プロジェクトのコンポーネントコードの変更。
メンタルモデル
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

キットは、コードに実在するシステムを検証可能な形で複製したものです。すべての色と寸法は、リポジトリ内の定数または関数までたどれる必要があります。コードに明記されていないため仕様に基づいて描画する箇所は、明示する必要があります(RULE-04)。

入力と出力の契約
フィールド必須?意味
入力トークンのソースはい色、文字、形状、サイズを生成するファイル/関数(例:lib/tokens.ts → paletteOf)
入力コンポーネント一覧はい種類名(kind/コンポーネント名)と、アプリ内の分類(palette、sidebar、docs など)
入力対象プラットフォームはいモバイル/デスクトップ/両方と、実際のフレームサイズ
出力docs/ui-kit.html(またはユーザー指定のパス)はい以下の 7 セクションをすべて含み、file:// から開ける 1 ファイル
出力出典レポートはいコードから取得した箇所と、仕様に基づいて描画した箇所
出力Playwright の証跡はいJS エラー 0 件、390px で scrollWidth - innerWidth = 0、ライトモード+ダークモード+サンプル画面のスクリーンショット
出力キットリポジトリ上のバージョンはい(UI_KIT_SYNC=0 の場合を除く)PRIVATE リポジトリ Rheinmir/ui-kits(W09)上の <id>/vN/index.html + manifest.json + registry.json のエントリー
ルールと機能
  • RULE-01 (MUST):色と寸法は、プロジェクトのコードを実行して取得します(一時的なテストランナー/スクリプトを使い、ダンプ後に削除します)。16 進数を手入力してはいけません。コードを読み取れても実行できない場合(CSS 変数、JSON など)は、ファイルを解析します。
  • RULE-02 (MUST):すべてのコンポーネントクラスは CSS 変数(--<ns>-<role>、--k)のみを参照します。コンポーネント CSS に個別の hex/rgb を含めてはいけません。これにより、:root ブロックと CSS の .<ns>-* を別のプロジェクトに移しても動作します。
  • RULE-03 (MUST):各コンポーネントのカードには、コード内の正確な名前(kind/コンポーネント名と主要フィールド)と、コードで使用されている寸法(dp/px)を記載します。
  • RULE-04 (MUST):仕様に沿って描画した部分や簡略化した部分(例:アニメーションのモーフィングを回転のみで表現)を、レポートにすべて記載します(必要に応じてカードにも注記します)。1 対 1 の複製として提示してはいけません。
  • RULE-05 (MUST):以下の 7 つの構成要素をすべて含めます。欠けている項目がある場合は、レポートに理由を記載します(例:アプリにデスクトップ版がない)。
  • RULE-06 (MUST):ファイルは自己完結型にします。フォントは Google Fonts からのみ読み込み、JS/CSS はインラインにし、ビルドや外部データの取得は行いません。
  • RULE-08 (MUST):骨組みだけで終わらせないでください。 コンポーネントの一覧は、既知のページやファイルをいくつか確認するだけではなく、W01b の探索サイクル(リンクをたどり、隠れたセクションを開き、飽和するまで探索)から作成します。inventory.json 内の各パターンには、キット内に data-sig="<sig>" を持つカードを用意するか、<meta name="ui-kit-skip" content="<sig>:<理由>;…"> を使って理由を記載し、対象から除外します。ゲート:node references/discover.mjs --coverage inventory.json kit.html の rc が 0 であること。
  • RULE-10 (MUST):コンポーネントを休止状態だけにしないでください。 W01b で計測した各状態(hover、focus-visible、active、selected)をキットに含めます。その状態を示すバリエーションをカードに表示し(サイトの :hover などのルールを正確に複製した is-hover/is-focus/is-active/is-on クラスを使用)、data-sig-state="<sig>:<state>" を付与します。または、ui-kit-skip の "<sig>:<state>:理由" を使って理由を記載し、対象から除外します。フォーカスがブラウザーの outline:auto のみ(ua: true)の場合は、キットに「フォーカスはブラウザーのデフォルトで、サイト独自のスタイルはありません」と明記します。ゲートの --coverage は状態もカウントします。
  • RULE-11 (MUST):robots.txt とサイトの利用規約を遵守します。 discover.mjs はスキャンの前に /robots.txt を読み込みます。User-agent: * によって開始パスがブロックされている場合、または自動収集を禁じる記載がある場合(例:facebook.com)は、rc 3 で停止し、--i-have-permission を自分で追加してはいけません。このフラグは、ユーザーが許可を得ていると確認した場合に限り使用します。代わりに、B05 としてユーザー自身がページを保存する方法を提案します。
  • RULE-09 (MUST):他者のサイトがソースの場合、そのサイトの画像、ロゴ、SVG ワードマーク、著作権で保護されたコンテンツをキットに埋め込まず、「画像…」と明記したプレースホルダーブロックに置き換えます。キットを PRIVATE リポジトリに自動同期すること(W09)は問題ありません。そのリポジトリの外部に共有(公開リンク、ホスティング)する場合は、事前に確認します(B03)。
  • RULE-12 (MUST):PASS したキットのみを同期します(W05b と W06 が緑であること)。同期先は PRIVATE リポジトリのみです。sync-kit.py は visibility を自動確認し、PUBLIC リポジトリを拒否します(GH#187)。バージョンは増加のみとし、古い vN を上書きしたり削除したりしません。
  • RULE-07 (SHOULD):作業時はサンプルファイル references/ui-kit-reference.html を隣に配置します。そのフレーム、ページ外枠の CSS、操作用スクリプトを再利用し、トークン、コンポーネント、サンプル画面のみを置き換えます。
  • 機能:コードベースの読み取り、プロジェクトのテストランナー/スクリプトの実行、HTML ファイル 1 つの書き込み、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・キットの出所と再利用方法を説明する段落 1 つ・重要なレイアウト定数を示す「facts」欄.intro .facts
4基盤(a) **色:**すべての役割、正しい組み合わせの色文字を持つ on* カラーサンプル、クリックで hex をコピー · (b) **文字:**名前と size/line-height/weight を含む文字スケール · (c) シェイプ:--k を乗じた角丸スケール · (d) **レイアウトとサイズ:**主要コンポーネントのサイズスケール表+フレーム/余白/間隔の定数表#color #type #shape #layout
5コンポーネントアプリの分類に合わせてグループ分け(例:アクション · ナビゲーション · コンテンツ · 入力 · フィードバック)。各 .spec カードは、ヘッダー(読者向けの名前+コード上の名前を示すチップ+寸法)→ .stage に重要なすべてのバリアント/サイズ/状態を表示 → フッター(注記+自動で付与される Copy HTML ボタン)で構成します。カードには対象となるパターンの data-sig を付けます(RULE-08)。インベントリに多数のパターンがあるグループは、パターンごとにカードを分け、共通のカードにまとめないでください#actions #navigation #containment #inputs #feedback
6サンプル画面アプリが対応している場合、アプリの正確なフレームサイズで モバイル画面を 1 つ以上、デスクトップ画面を 1 つ以上用意し、zoom で縮小します。セクション 5 の実際のコンポーネントクラスを使い、アプリのレイアウト規則に従って組み合わせます(例:モバイルではボトムナビ、デスクトップではナビゲーションレール+リスト詳細)。フレームの下に、使用したコンポーネントを列挙する注記を付けます#screens .phone .desk
7スクリプトdump から生成した ROLES と PALETTES[key].light/dark 形式の埋め込みトークン表 · :root に CSS var を書き込む apply() · データから色サンプル/文字スケール/シェイプスケールをレンダリング · コピーボタンを設定 · コピー完了を知らせる toast(clipboard がブロックされた場合は手動コピーを案内)ファイル末尾の <script>

ページ全体に適用する事項:ページの外枠にはキット自体のトークンを適用します(ページのテーマ変更をコンポーネントにも反映)。prefers-reduced-motion ではアニメーションを無効にします。:focus-visible を明確にします。アイコンボタンには aria-label を付けます。390px のモバイル画面で横にはみ出さないようにします(表/サンプル画面は overflow-x:auto のコンテナー内に配置)。

障害の境界
  • トークンのソースが見つからない場合(コンポーネント内にハードコードされた色が点在している場合)→ 部分的:grep で実際に使用されている色をまとめ、「トークンのソースがなく、色はコンポーネントから推定」と明記し、トークンの切り出しを提案します(別作業)。
  • サイトが独自のコンテナー内でスクロールする場合(body の高さが画面1枚分)→ fullPage では画面1枚分しかキャプチャされません。discover.mjs はキャプチャ前にコンテナーを自動で開きます。自作スクリプトでも同様にしてください。
  • 状態が JS の実行時にのみ存在する場合(クリックで開くメニュー、遅れて表示されるツールチップ、開始時のアニメーション)→ 純粋な CSS の :hover は測定できますが、JS に依存する状態は見落とされる可能性があります。W01c で *-hover.png のクロップ画像を確認して、必要に応じて自分で追加してください。押下状態(active)は mouse.down → マウスを外へドラッグ → mouse.up で測定するため、リンクはアクティブになりません。測定できない場合は、レポートに明記してください。
  • JS を無効にしたページ(B05):FDS Facebook の hover/pressed オーバーレイなど、JS が付与する状態は測定できません。対応するトークン(--hover-overlay、--press-overlay)から再現し、「トークンから再現、未測定」と明記してください。ページが非常に重い場合(3000 個以上の要素があるフィード)は、--page-timeout を大きくする必要があります。
  • ページ探索が上限に達し(stoppedBy: page-budget)、最後のページにまだ新しいパターンがある場合 → ユーザーに報告し、--pages の増加または --include の絞り込みを提案してください。キットが十分だとはみなさないでください。
  • 実行時にしか使えないトークン(DB/アプリサーバーが必要な場合)→ 実行中のアプリで Playwright を使ってダンプします(:root に対する getComputedStyle)。取得方法を明記してください。
  • プロジェクトにプラットフォームが1つしかない場合 → セクション6にはその画面のみを掲載し、理由を明記してください。
  • 3回修正した後も Playwright が JS エラーまたは横方向のはみ出しを報告する場合 → 作業を中止し、残っているエラーを報告してください。
  • W09 の同期でネットワークエラーが発生した場合、push 権限がない場合、またはリポジトリが PRIVATE でない場合 → スクリプトは rc 0 で「未同期、理由…」と表示します。ローカルのキットも有効な成果物です。W08 に理由を記載してください。

方法

主なワークフロー
ステップ種類入力アクション出力/終了条件失敗時/次の対応
W01判断codebaseトークンのソース、コンポーネントの一覧とグループ、モバイル/デスクトップの枠サイズ、スキーマドキュメント(あれば)を探しますアンカーの一覧 file:lineトークンがない → 部分対応(「失敗時」を参照)
W01b決定論的元の URL(開発用アプリまたはサイト)探索ループ:NODE_PATH=$(npm root -g) node references/discover.mjs <url> --out <scratch>/disc --pages 32 --saturate 4(グローバルに Playwright が必要、約40秒/ページ、バックグラウンドで実行)。同一オリジンのリンクを BFS でたどり、内側のコンテナもスクロールし、アコーディオン/タブ/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 → 予算を増やします(「失敗時」を参照)
W01c判断crops + ページのスクリーンショット新しい crop と全ページのスクリーンショットをすべて確認します。パターンを kit グループにまとめ、分類器が見落とすパターン(例:台形タブ、フロー図)を構築対象一覧に記録しますパターン → グループ → kit カードの表—
W02決定論的トークンのアンカー実際のトークン関数を呼び出す一時的なテスト/スクリプトを書き、JSON をダンプします(すべてのパレット × ライト/ダーク、サイズスケール)。一時ファイルは削除しますscratchpad 内の tokens.json実行エラー → 静的解析
W03効果JSONROLES + PALETTES にまとめ、テンプレートファイルのコピーに埋め込みます<script> 内のデータブロック—
W04判断コンポーネントコードセクション 4~5 を書き直します。各コンポーネントはコードの実測値を使った単一の .<ns>-* class とし、.spec カードには header/stage/footer を含めますセクション 4~5コードに実測値がない → spec に基づいて描画し、明記します(RULE-04)
W05判断アプリのレイアウト規則W04 の class を使ってセクション 6 を組み立てます。モバイル画面とデスクトップ画面を用意しますセクション 6アプリが単一プラットフォーム → 理由を記載します
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 を数え、ページ上部・中部・サンプル画面を撮影します。ダークモード+別のパレットに切り替えて再撮影し、viewport 390 で横方向のはみ出しを測定しますスクリーンショット + 数値エラー → 修正し、最大3回繰り返します
W07判断スクリーンショットスクリーンショットを一通り確認し、目視できるレイアウトの不具合(テキストの折り返しが詰まっている、項目の位置ずれなど)を修正して、1回再撮影しますkit 完了—
W08判断結果ユーザーに報告します:ファイルパス、7セクションの内容、コードに基づく箇所/spec に基づく箇所、W06 の証拠、W09 の同期結果報告—
W09効果W05b + W06 を PASS した kitpython3 references/sync-kit.py <kit.html> --source <リポジトリのディレクトリ | 元の URL>(ソースから id を推測できない場合、例:ログイン後のアプリでは --id <id> を追加)。Id:リポジトリの場合は origin から <owner>-<repo>(remote がない場合は <ディレクトリ>-local)。URL の場合は www. を除いた host を使い、ドットをハイフンに置換します。ui-kit-id の meta を除外して sha256 を計算します。最新版と同一なら「vN から変更なし」とし、commit しません。異なる場合は vN+1 + latest/ を作成して push します。拒否された場合は pull して再計算し、最大3回まで試行します。UI_KIT_SYNC=0 でスキップできます。UI_KIT_SYNC_REPO でリポジトリを変更できます✓ <id>: vN → <link> または = 変更なしエラー →「未同期、理由」を出力し、rc 0(「失敗時」を参照)

トークンダンプの例(vitest、TS): lib/zz-kit-dump.test.ts を作成してトークン関数を呼び出し、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_requiredアプリにエージェント向けのスキーマ文書がある(例:agent.md)「コード内の名前」チップにはスキーマのフィールド名をそのまま記載し、サンプル画面にはその文書のルールを適用しますない場合 → コンポーネント名を使用W04
B04conditional_requiredソースが稼働中のサイトの URL(コードなし)W02 を Playwright に置き換えます。:root/.dark の CSS vars と実際の要素の getComputedStyle を読み取り、lab()/oklch() の色を hex に変換し、RULE-09 を適用しますコードがある場合 → スキップW03
B05conditional_requiredサイトがクローラーを禁止している(RULE-11)、またはログイン後にのみ表示される UIユーザーがページを「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 を無効にして、スクリプトがサイトへ自動リクエストしないようにします)。保存したページに個人データが含まれる場合、kit はスタイル/構造のみを取得し、名前/画像/コンテンツをすべてサンプルに置き換え、実際の名前が残っていないことを引き渡し前に grep で確認しますサイトがクロールを許可 → 通常の W01bW01c
B03user_optionalユーザーが共有リンクを kit のプライベートリポジトリの外部に公開したいファイルをユーザーが選んだ Artifact/ホスティングにアップロードします。ファイルはリポジトリにも残します既定:ローカルファイル+プライベート kit リポジトリ(W09)W08
検証と停止

自動検査:W09 の決定論的テスト python3 -m pytest harness/tests/test_ui_kit_sync.py(id、hash、バージョン番号、v1 の不変性);W05b のカバレッジゲートは rc 0(すべてのパターンに data-sig または ui-kit-skip があること);W06 は pageerror = 0 かつ 390px で横方向のはみ出し = 0 である必要があります。目視検査:構造表にある 7 つのセクションがすべて揃っていること、ライト/ダークのスクリーンショットを比較すること、Copy CSS token ボタンと Copy HTML ボタンを 1 つずつ試すこと。W06 での修正は最大 3 回、W07 での再撮影は 1 回のみです。

例
  • Positive: m3e-canvas(Next.js、Material 3 Expressive エディター)。paletteOf() を vitest でダンプし、7 パレット × ライト/ダークを取得。キットには 25 のカラー役割、15 の文字スタイル、3 段階のシェイプ、アプリの Parts テーブルのように 5 グループに分けた約 30 個のコンポーネント、モバイル 412×892(リスト+詳細)とデスクトップ 1280×800(レール+リスト・詳細)を収録。Playwright でエラー 0 件、390px でオーバーフローなし。主な成果物は references/ui-kit-reference.html です。
  • Positive(URL): drafted.ai。初回は既知の 3 ページだけをスキャンしたため、キットは骨組みだけでした。/learn/ai-for-homebuyers から --pages 32 --saturate 4 を指定して W01b を実行:discover.mjs が 32 ページ(learn、use-cases、住宅一覧ページ、FAQ、ニュース、採用情報、オンボーディング)を巡回し、171 パターンを収集。新しいものが 4 ページ連続で見つからずに停止しました(1 ページあたり約 40 秒)。W05b の初回結果は カバレッジ 62/171 (36%) でした。住宅一覧、記事とセクション、inventory から生成した実際の文字テーブルの各グループを追加し、22 件の ui-kit-skip(画像、サードパーティーの埋め込み、ページフレーム)を記録した後、ゲートは カバレッジ 171/171 (100%) を報告しました。W01c では、分類器が見落としていた SVG 描画の台形タブも追加で検出しました。 3 回目のイテレーションでは状態の計測を追加:175 パターン、104 状態(hover 44、focus 56、active 1、selected の組み合わせ 3)。初回は 状態 0/104 でした。状態ストリップ 23 個と「Focus · 2 styles」カードを追加した後、ゲートは 175/175 + 104/104 を報告しました。計測により、それまで誤って推測されていた hover ルール 6 件も修正されました(例:選択カードの hover は stone-900 ではなく stone-500 に変化)。また、focus 56 件中 44 件はブラウザーのデフォルトのアウトラインにすぎないことも判明しました。
  • Positive(B05、サイトがクローラーを禁止): facebook.com。robots.txt が自動収集を禁止しているため、discover.mjs は rc 3 で停止し、agent が user に確認します。User は 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 件、外部リクエストは 0 件でした。
  • 境界/失敗: React リポジトリでは、.module.css 40 ファイルに hex カラーが散在し、トークンがありません → 部分的な結果:grep で実使用カラー 18 件を検出し、キットには「コンポーネントから推定した色」と記載。キットを完全に作成する前に、トークンを分離することを提案します。

コメント