interface-bts について
interface-btsは、既存のUIインタラクションをA4仕様ポスターにまとめるスキルです。開発者が実行中のコンポーネントを追跡・測定し、再設計せずにポスターを構成して検証できます。
主な機能
- 01操作のトリガーと出力の追跡
- 02実行中のコンポーネントの値を測定
- 03注釈とモーション曲線の表示
- 04選択可能な動作時点の記録
- 05A4ポスターの構成と検証
活用シーン
- 01ドロップダウンの遷移動作の記録
- 02ドラッグやスクロールの入力マッピングの説明
- 03視差効果を減らす設定時の動作記録
- 04測定に基づくUI仕様の作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ nomanjack/ interface-bts --skill interface-btsインストール後、Claude Code で/interface-btsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
README.mdLICENSEassets/example/copy.module.csscopy-spec-sheet.tsxsource-copy.tsxassets/kit/sheet-states.tsxsheet-states.module.csssheet-playback.module.csssheet-playback.tsxsource-kit.tsspec-kit.tsxspec.module.cssreferences/drafting.mddrivers.mdscripts/overlaps.js詳細
interface-bts
このスキルは、プロジェクト内の1つのインタラクションを、A4サイズの仕様ポスターに変換します。動きの裏側を描いた図です。ポスターには次の内容が含まれます。
- 図1: 実際のコンポーネントを動作途中の状態で切り取り、サイズを寸法として記載します。
- 注釈: 番号付きのパーツ。それぞれに、何が変化するのか、なぜ変化するのかを説明する注記を添えます。
- 図2: 動きを決めるカーブまたはマッピング。
- モーメント: コンポーネントを再度動かすために選べる状態を並べた行。
- 仕様: トリガー、プロパティ、時間、イージング、動きを抑える設定。
読者が、仕組みについて一文で説明できるようにします。
このポスターは、インターフェースが現在どのように動作するかを記録します。再設計でも、実行中のデバッグオーバーレイでも、動画でもありません。コンポーネントを変更したい場合は、その旨を伝え、ポスターには反映しないでください。ポスター上の数値はすべて、実行中のコンポーネントから取得します。読み取れない値は推定値と明記し、推測で埋めることはありません。
例:/interface-bts the dropdown in components/menu.tsx
1. インタラクションを調べる
- コンポーネント、その呼び出し元、スタイル、ハンドラー、アニメーションコードを見つけます。実行して、自分でインタラクションを試します。
- 入力 → 判断 → 出力をたどります。
- 何がトリガーになりますか?
- 何が変化しますか?
- どの値が変化を決めていますか(時間、イージング、しきい値、サイズなど)?
- それぞれの値はどこにありますか?
- ルールがわかるケースを試します。ゆっくりした入力、反転、中断、静止状態、動きを抑える設定を確認します。
完了条件: 仕組みを一文で説明でき、使用される各値の出典を示せること。
2. チャットでポスターの内容に合意する
以下を列挙し、作成に取りかかる前に了承を得ます。
- 見出し: 仕組みを平易な言葉で表します(「ピル型の要素が追いつく:左端と幅が1つのカーブに沿ってイージングする」)。
- 主役となるモーメント: 仕組みが最もよくわかるフレームです。通常は動作の途中、またはしきい値を超えた直後で、静止状態になることはほとんどありません。
- モーメント: 物語の流れに沿った3~5個の状態(静止、開始、主役、しきい値を超えた状態、整定)。
- 注釈: 図1に示す2~4個の番号付きパーツと、それぞれの注記の内容。
- 図2: 以下の表から選びます。
- 測定値: 見出しの説明に必要な1つか2つのサイズ。
| 説明する内容 | 図2に描くもの |
|---|---|
| 時間経過に伴う値の変化(ほとんどのトランジション) | イージングカーブと、カーブ上に示した静止モーメント |
| 1つの時計に沿って動く2つの要素(クロスフェード、アイコンの切り替えなど) | 1つの時間軸上に2つのカーブ |
| 入力に追従する値(ドラッグ、スクロールなど) | 入力と出力のマッピング、およびクランプ点とスナップ点 |
| キーフレームまたはループ | 1サイクルにおけるキーフレームの停止位置 |
| しきい値またはスナップ | 現在の入力を含む判定領域 |
完了条件: ユーザーが見出しとモーメントに合意していること。
3. 実際のコンポーネントを固定する
- 図1は実際のコンポーネントです。 独自のハンドラーで動かし、実際のアニメーションを一時停止して固定します。
getAnimations()を呼び出してからpause()を呼び、currentTimeを設定するか、アニメーションライブラリ独自のタイムラインをシークします。決して作り直したり、模倣するために別のアニメーションを実行したりしないでください。 - 実行中のコンポーネントから数値をすべて読み取ります。 計算済みスタイル、
getAnimations()、そのタイムライン、またはコンポーネントが公開するデータ属性から読み取ります。ポスターに期間、イージング、しきい値を直接入力してはいけません。firstEasing()で最初のタイミング関数を取得してください。計算済みのリストをカンマで分割すると、cubic-bezier()が途中で分断されます。 - CSS トランジションではないコンポーネントには、専用のドライバーが必要です。 また、ポスターと相性が悪いものもあります。floating-ui によって配置されるもの(Radix のメニュー、ポップオーバー、ツールチップ)、ウィンドウに固定されるもの(トースター、シート)、画面上で自身の位置を測るもの(ドラッグやスワイプのしきい値)、フォーカスを移動するものなどです。こうしたものを実装する前に、references/drivers.md を読んでください。
- 複数のチャンネルを1つの動きとして見せる前に、チャンネル間の整合性を確認します。 たとえば、不透明度がスケールと同じ曲線に従っているかを確認します。異なる場合は、誤った図ではなく、エラー状態をポスターに表示します。
- 各時点はコピーです。 計算済みスタイルをインライン化した、静的な DOM スナップショットであり、操作できません。すべてに同じカメラを使い、拡大が縮小に見えることのないようにします。
- 測定した内容を報告します。 コードの意図と食い違う場合も同様です。
完了条件: 各時点でコンポーネントを毎回同じフレームに再駆動でき、固定した値が元のコンポーネントと一致し、(ジェスチャーやポインターパスを駆動する場合は)実際のブラウザーでマウスまたはタッチを使って1回の実行を検証していること。
4. ポスターを構成する
- 常に A4 縦向きにします。 まず 794 × 1123 のアートボード(96 dpi の A4)上にレイアウトし、ポスター全体を空間に収まるよう中央に配置して拡大縮小します。ブレークポイントで再配置してはいけません。サイズ変更で変わるのは倍率であり、配置ではありません。
- 順序: コンポーネント名、その下に各時点を配置した図1、続いてフッターです。フッターでは、注記と図2を横並びにし、その下に仕様を幅いっぱいに配置します。一番下には、単位、作図倍率、線種を一度だけ記したタイトルブロックを置きます。
- 文字:
- コンポーネント名は 16px、ウェイト 500 とし、唯一の見出しにします。
- 注記と仕様は 13/18 にします。
- 図の中は 12px にします。
- フォントは1種類、文頭のみ大文字にし、ウェイトは 600 を超えないようにします。
- 数字は等幅数字にし、単位は数字より薄くします。
- 余白: 上下 20px、左右 32px にします。
- 各図を割り当て枠に合わせてサイズ調整します。 空き高さを測定してから、コンポーネントと寸法が収まる作図倍率を選びます。倍率を「3×で作図」のように明記します。
- 外枠は付けません。 注記や図の周囲にカードや枠を置かず、細線とフラットな塗りを使います。光彩、大きくぼかした影、奥行き表現のためのグラデーションは使いません。
- アクセントカラー:
- 各ポスターには、iOS 26 のシステムカラーを1色使います(キット内の
IOS26)。プロジェクト内のポスターごとに異なる色を選び、SPEC_ACCENTSに記録します。 - 12色すべて使い切ったら、使用回数が最も少ない色を再利用します。
- アクセントカラーは線と塗りに使い、実行部分の下には 12% の色合いを敷きます。文字には同じ色相の濃い色を使い(明度は 0.52 以下)、黄色やミント色でも読みやすくします。
- 各ポスターには、iOS 26 のシステムカラーを1色使います(キット内の
- テーマ: アプリの実際のテーマを使います。アプリ自体がダークモードの場合に限り、アプリ独自の仕組みから判定して
theme="dark"を渡します。独自にダークテーマを作ったり、ポスターにテーマ切り替えを置いたりしてはいけません。テーマが判明するまで何も描画せず、テーマをポスターのキーにして、変更時に再描画し、各時点のコピーも作り直します。
基準点からの寸法、線種、詳細図、整列した図の作図規則については、references/drafting.md を参照してください。作図する前に読んでください。
完了条件: ポスターのすべての要素に配置場所があり、コンポーネントに文字が重なっていないこと。
5. 仕上げてから、計測で検証する
仕上げ:
- 光学的な位置合わせ: 番号は1行目のベースラインに配置し、フットの列は最初のベースラインをそろえ、注記と図は左端をそろえます。
- 同心円の半径: 部品の周囲に描く輪郭には、描画スケールでの部品自体の半径を使います。内側に配置するものには、外側の半径から隙間を差し引いた値を使います。
- 端を柔らかく: 製図グリッドは半径方向にフェードアウトし、モーメントの行は両端でフェードします。暗く表示されるモーメントは、フェードに合わせて少しぼかします。
- 引き出し線は部品から45°で伸ばすか、隙間が唯一の明確な経路であれば、まっすぐ横切ります。
- **注記にホバーすると、**別の注記が付いた部品はすべて暗く表示されます。
検証:
- 重なり:
scripts/overlaps.jsをページに貼り付け、1280×800、1000×760、1030×1044の各サイズで、すべてのモーメントについてbtsOverlaps({ overlay: '[data-poster] svg', subject: '[data-poster] [inert] > *, [data-poster] [data-subject-root]' })を実行します。対象は図全体ではなく、コンポーネント自体のルートです。そうしないと、すべてのラベルが図と重なっていると判定されます。何も返されない必要があります。1つのラベルではなく、配置ルールを修正します。 - フィット: これらのサイズではページがスクロールせず、サイズ変更で変わるのはスケールだけです。
- モーメント: それぞれを選択します。コンポーネント、注記、曲線がすべて連動し、コンソールにエラーが出ないことを確認します。
- ソースと値を照合して固定する: たとえば、ポスターの表示時間をスタイルシートと照合します。
- 動きを減らす設定: ポスターは実態に即している必要があります(動きがない場合はモーメントの行を表示しません)。動きを減らす設定をオンにして、仕様の記述を確認します。アプリ全体に適用されるルールが、ライブラリ独自のトランジションを上書きすることがあります。
- 非表示のタブ: 埋め込みプレビューやバックグラウンドのプレビューでは、rAFが動作しない場合があります。
document.hiddenを確認し、スクリーンショットにはヘッドレスのPlaywrightを使います。
すべてのチェックに合格したら完了です。実行できなかったチェックがあれば、その内容を伝えます。
キット
assets/kit/ は、上記すべてを実装した React と CSS Modules のキットです。プロジェクトにコピーし(Next.js では app/specs/kit/、それ以外では src/specs/kit/)、各ポスターをその隣のページとして作成します。完成したコピーボタンのポスターが assets/example/ にあるので、そこから始めてください。
-
spec-kit.tsx:-
SpecPage: ポスターです。プロパティ:accent、name、label;drawing(図 1)、moments、notes、specの行、fig2、units;ready、error、onRetry;theme。
-
useTransitionSpec({ fractions, setup }): CSS トランジション用のドライバーです。setup(root)は次を返します:base(静止時の値);easing;trigger(コンポーネント独自のハンドラー);read(実行中に読み取る値);- アニメーションから選択するための任意の
pick。
次を返します:
m:保持された値。elapsed、duration、easing、reducedを含みます;snapshots、selected、select;ready、error、retry;root:コンポーネントのラッパー用の ref。
-
描画:
Overlay;DimとVDim(寸法);Callout;markClass(線の種類とハッチング);useCrisp(デバイスピクセルにスナップする極細線);useDrawingScaleと、画面倍率 1 で表示する必要があるコンポーネント用のuseScreenScale。
-
図:
Curve;Timeline;Moments(変化する部分だけを表示するcrop付き)。
-
読み取り:
firstEasing、easeAt、easeWords;stopsOf、sampleStops、scaleOf(キーフレーム:ループでは 1 サイクルを使用します);within(ボックスの寸法を 0.1px 単位で取得);UとUt(単位部分を薄く表示した数値)。
-
-
source-kit.ts:useDataState:状態をデータ属性に保持するコンポーネントを操作します;startWithout:トランジションなしで開始位置に配置します;ms:CSS の時間を解析します。
-
sheet-states.tsx: スナップショットのキャプチャとモーメントの行です。oneCamera(spec-kit.tsx内)は、1 つのフレームにモーメントを 1 つずつキャプチャして配置します。 -
sheet-playback.tsx: 再生、停止、スロー再生に対応します。これらを提供するポスター向けです。
スクロール、ジェスチャー、ポインターパス、または JS アニメーションライブラリを使う場合は、useTransitionSpec と同じ形状の小さなドライバーを作成し、ライブラリ独自のクロックをシークしてください。references/drivers.md を参照してください。React の外では、レイアウトと規約を移植してください。キットは参考用であり、依存関係ではありません。
納品
ポスターの URL、1280×800 のスクリーンショット、見出しを提示してください。続けて、次の項目を列挙してください:
- 測定した内容;
- 推定として示した項目;
- 実行できなかった確認事項。