mcpField
S
sb-stories

sb-stories

github.com/strongeron開発3981 回インストール4 週間前に更新
リポジトリ

sb-stories について

sb-storiesは、コンポーネントやページのStorybookストーリーを作成する開発者向けスキルです。実際の利用状況と重要な状態を重視し、検証スクリプトで成果物を確認します。

主な機能

  1. 01重要な状態のストーリー作成
  2. 02利用データに基づくバリアント選定
  3. 03実ページの読み込みとデータのモック
  4. 04Controls、オーバーレイ、操作の扱い
  5. 05スクリプトによるストーリー検証

活用シーン

  1. 01既存コンポーネントの状態ストーリー追加
  2. 02実ページと異なるデータ状態でページストーリーを作成
  3. 03複数コンポーネントのストーリー作成と検証

MCP 対応

プロジェクトのMCP設定の有無に応じて執筆ガイドを選びます。WITH_MCPの手順では、MCPがCSF3の規約を提供します。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/strongeron/storybook-workbench --skill sb-stories

インストール後、Claude Code で/sb-storiesを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

CONTEXT.md
agents/
openai.yaml
references/
anti-patterns.md
composition-patterns.md
directory-structure.md
extraction-workflow.md
factory-patterns.md
storybook-surface.md
test-wiring.md
validate-workflow.md
with-mcp.md
without-mcp.md
scripts/
check-story-ready.sh
discover-runtime.py
extract-prop-shapes.sh
extract-states.sh
page-patterns.py
scaffold-factory.sh
scaffold-page-story.py
validate-stories.sh
templates/
controlled-component-story.tsx

詳細

sb-stories — 1 つのコンポーネント、その実際の状態

デフォルトの Build モードです。コンポーネントは src/components/ にあり、その表示状態を示すストーリーを記述します。

作成前に確認すること

  • 実際に使われていますか? .storybook/project-inventory.json の components.real[] を確認してください。dead[] に含まれている場合は削除し、ストーリーは作成しないでください。vendor(shadcn の ui/)の場合は優先度を下げてください。
  • 動作や見た目が大きく変わる状態はどれですか? 直積の組み合わせは避けてください。プリミティブごとの最小テーブルは references/anti-patterns.md にあります(Button 8、Input 8、Modal 5、Form 6)。推測するのではなく .storybook/component-states.json を確認してください。ファイルがない場合は、先に生成してください: scripts/extract-states.sh。(より大きな抽出コンテキストについては references/extraction-workflow.md を参照してください。)それらすべての状態を1つのキャンバスにレンダリングするには、sb-wrappers の StateGrid ラッパー(variants × states → StateMatrix)を使ってください。グリッドを手作業で作成しないでください。これらはコンポーネント作成時のラッパーです。データラッパー(ProjectInventory/DesignSystemHealth/AppFlowGraph …)は、それぞれの手順の後に使います。
  • このアプリで実際に使われている状態はどれですか? .storybook/component-usage.json を確認してください(sb-inventory の extract-component-usage.sh で生成します。ファイルがない場合は生成してください)。props.<prop>.values を使って、実際の呼び出し箇所で渡されているバリアントを優先してください。declaredButUnused に含まれるもの(例:variant=danger が一度も使われていない場合)についても、網羅性のために状態を作成しますが、['usage:unused'] タグを付けて「このアプリでは未使用」と記載してください。本番環境でレンダリングされない状態でカタログを水増ししないでください。
  • コンポーネントごとのドキュメントを手作業で作成する必要はありません。すべて一度だけ合成されます。 各コンポーネントの autodocs ページには、すでに**「このアプリでの実際の使用例」のセクションが追加されています。sb-setup によって preview.ts の docs.page に一度だけ組み込まれる UsageSection ブロックが、使用状況グラフ(component-pages.json)から読み取った、コンポーネントごとの「使用箇所」**マップ(表示されるページ、内包する要素、レンダリング内容、参照するトークン)を表示します。そのため、ストーリーを追加したら、使用状況のブロックを手動で追加しないでください。 refresh-usage.sh を実行するだけで、グラフが最新になり、セクションに内容が反映されます。グラフ全体を対話的に調べるには(任意のトークン/コンポーネント/ページから、その使用箇所すべてに移動できます。クリック可能です)、UsageExplorer ラッパー(sb-wrappers)を構成してください。詳細と docs.page の構成については、sb-inventory(§「autodocs での実際の使用例」)および sb-setup(docs-page の構成)を参照してください。
  • ファクトリーは必要ですか? 同じデータ形状を共有するストーリーが3つ以上ある場合は必要です。.storybook/prop-shapes.json を確認してください(候補には liveUsages のフラグが付きます)。ファイルがない場合は、先に scripts/extract-prop-shapes.sh を実行してください。 次に scripts/scaffold-factory.sh <Type> <import-path> を実行し、決定論的なスタブに値を入れてください(references/factory-patterns.md)。それ以外の場合は args をインラインで記述します。
  • タイトルの分類はありますか? storySort.order に合わせてください。プロジェクトに設定がない場合は、references/directory-structure.md を参照して選択してください。
  • play を追加する価値はありますか? インタラクション、非同期データ、ポータル、CSS による状態、またはアクセシビリティの場合に限り作成してください。単に toBeVisible() を実行するだけのものは作成しないでください(アンチパターン34)。また、プロジェクトに必要な CssCheck はちょうど1つです(アンチパターン33)。共有プレビューでアプリの CSS が読み込まれていることを証明する唯一の手段として、実際の getComputedStyle のトークン値を検証するストーリーを1つ作成してください。どちらも npx storybook ai setup のプロンプトから追加されます。validate-stories.sh のチェック13とプロジェクト全体の件数チェックで必須になっています。
  • 「playground」/ショーケースストーリーは、クリックやホバーではなく Controls で操作します。 レビュアーから「この playground ストーリーとは何ですか?クリックやホバーはできますか?」と聞かれた場合、playground とは Controls パネルが付いたデフォルトストーリーのことだと説明してください。Controls タブで args(variant、size、state)を変更すると、キャンバスが再レンダリングされます。キャンバス上でのインタラクションではありません。ホバー/フォーカス/アクティブ状態は StateGrid のインタラクションマトリクス(addon-pseudo-states)で、スクリプトによるクリック→アサートのフローは play 関数で扱います。つまり、Controls はプロパティの試用、疑似状態はホバー/フォーカスの列、play は実際のインタラクションです。ストーリーがどれに該当するかを明示してください。
  • Controls パネルは設定されていますか? コンポーネントのストーリーには、使用可能な Controls パネルを表示する必要があります。これはレビュアーがプロパティを試すためのサンドボックスであり、autodocs の ArgTypes テーブルにも利用されます。react-vite のデフォルト(react-docgen)では、TS のユニオン型はセレクトとして推論されません。そのため、各 enum/union プロパティに argTypes(control: 'select'|'inline-radio' と options)を宣言し、table.category でグループ化してください。また、回避用のプロパティやシリアライズできないプロパティ(className、refs、icon/callback/data プロパティ)は非表示にし、レンダリングのみのショーケースストーリーでは Controls を無効にしてください(parameters: { controls: { disable: true } })。パターン全体と docgen の注意点については references/without-mcp.md §13 を参照してください。(パネル自体が表示されている必要があります。sb-setup は showPanel: true を設定した manager.ts を作成します。sb-audit の audit-controls.sh は、この設定がないコンポーネントストーリーを検出します。)

ソースの作成(相互排他的 — どちらか一方だけを読み込みます)

grep -q '@storybook/addon-mcp' package.json && test -f .mcp.json && echo WITH_MCP || echo WITHOUT_MCP
  • WITH_MCP → references/with-mcp.md(MCP が CSF3 の規約を適用するため、判断に集中できます)。 ツール名は Storybook のマイナーバージョン間で変わります。現在の名前は references/storybook-surface.md に記載されています。
  • WITHOUT_MCP → references/without-mcp.md(13 の検証ギャップと 4 つの重要な SB10 パターン)。
  • 制御コンポーネント(Switch/Toggle/Checkbox/Tabs/Accordion/Select)には、 templates/controlled-component-story.tsx を使用します。AI が間違えやすいのは useArgs による同期です。

ファイルの保存場所(先に確認してください — リポジトリ内に散在させないでください)。 .storybook/audit/status.md から storiesLocation を読み取ります(唯一のルールは CONTEXT.md §STORIES LOCATION にあります)。

  • 未設定の場合(リポジトリに既に Storybook があり、sb-setup で確認されていない場合など)、ストーリーを書く前に必ず停止してユーザーに確認してください — 推測したり、暗黙のうちに同じ場所に保存したりしないでください。AskUserQuestion(Claude)/request_user_input(Codex)を使うか、ブロックするツールがない場合は番号付きリストを使用します。

    ストーリーの保存先はどこにしますか?(それ以外はすべて .storybook/ の下にあります。)

    1. .storybook/stories/ (推奨 — 1 か所にまとめて分離し、src/ は変更せず、フォルダーごと削除できます)
    2. コンポーネントと同じ場所 src/**/<Name>.stories.tsx (長期的に所有するプロジェクト向け)
    3. カスタムフォルダー (指定した場所にまとめて保存します) その後、.storybook/audit/status.md に storiesLocation: <isolated|colocated|PATH> と記録し、 main.ts の stories にそのパスが含まれていることを確認してから続行します。オプション 1 を推奨します。
  • isolated(または .storybook/stories/) → .storybook/stories/ の下に、ツリー構造を反映して保存します (.storybook/stories/components/CourseCard.stories.tsx)。@/ エイリアスを使ってコンポーネントをインポートします。 開発サーバーは .storybook/stories/ を監視しません。そのため、ここでストーリーファイルを追加、移動、削除しても、Storybook を再起動するまではインデックスに反映されない(または古い状態のままになる)ため、すべての MCP ツールで「ストーリーが見つかりません」と報告されます。ここでファイルを変更した後は再起動してください(10.6.0 で確認済み。src/ のストーリーはリアルタイムで更新されます)。
  • colocated → src/components/<X>/<X>.stories.tsx。カスタムパス → すべてのストーリーをその場所に保存します。

回答にかかわらず、すべてのストーリーをその 1 か所に保存してください — 複数の場所に分けないでください。

タイトル(ファイルパスとは別の、Storybook 内のパス)は .storybook/preview.ts storySort.order に合わせます。該当しない場合は Components/<Domain>/<Name> を使用します。Overview/Spec/ハブストーリーはエントリーポイントです。storySort.order でルートの先頭に固定します(ルートレベルのハブは最初に配置し、機能ごとの Overview/Spec はグループ内のサブ順序で最初にし、末尾に '*' を置きます)。要約対象のコンテンツの途中にアルファベット順で紛れ込ませないでください。references/directory-structure.md の「Overview/spec/hub」を参照してください。

ページ — 実ページのキャプチャ(モード A)

ページ(pages/ · app/ · routes/ · views/ 配下のルート/ビュー)は再作成しないでください。 まず scripts/page-patterns.py <root> を実行します。ページごとに importable、component、 layout、dataHook とモックの手がかりとなる dataType、レンダリング順を示す sections(ui/ は除外)、gridHint がレポートされます。さらに sharedSections[] も確認できます。 その後、importable に応じてモードを選びます。

  • importable: true(ページに default-export コンポーネントがある)→ 実際のページをそのままインポートし、 データレイヤーのみをモックします。 scripts/scaffold-page-story.py <root> <page-suffix> でスキャフォールドします。 実際のページをインポートし、検出されたプロバイダー(Inertia usePage / router / store)を接続する Pages/<Name> ストーリーが生成されます。props は、dataType をキーにしたファクトリーから シードされます(references/factory-patterns.md に従い、scripts/scaffold-factory.sh <dataType> <import-path> を使用)。 実際に異なる データ の状態(空/データあり/エラー)ごとにストーリーを 1 つ追加します。異なるのはファクトリーの入力であり、 マークアップではありません。ページの JSX を書き直してはいけません(アンチパターン 27)。 レイアウト、カラム、コンポーネントは実際のページのものを使います。
  • importable: false(インラインで組み立てられている/単一のコンポーネントがない)→ ページ構成 (references/composition-patterns.md の Pattern 4)に切り替えます。実際の sections から組み立てます。 引き続きファクトリーを使用し、実際のコンポーネントを使います。

sharedSections[](2 つ以上のページでレンダリングされるセクション)は、再利用可能なページパターンの要素です。 それぞれに独自の Components/* ストーリーを用意し、ページ間で重複させずに組み合わせて使います。

autodocs のオーバーレイ(Dialog / Modal / Sheet / Drawer / Popover)

開いたオーバーレイは、position:fixed inset-0 のオーバーレイを document.body にポータルします。 autodocs ページ上にインラインでレンダリングすると(Primary ブロックと同じ方法)、 オーバーレイが Docs ページ全体 を覆ってしまいます。その結果、タイトル、「実際の使用例」セクション、 Controls が空白の背景の裏に隠れます。したがって、autodocs を使うオーバーレイコンポーネントでは、 ストーリーを専用の iframe に限定します。

parameters: {
  layout: 'fullscreen',
  docs: { story: { inline: false, height: '640px' } },  // portal stays inside the frame; Docs prose stays readable
}

ストーリービュー(1 つのストーリーをキャンバス全体に表示するビュー)には影響しません。これは Docs ページに限った設定です。 オーバーレイ以外のコンポーネントには適用しないでください(インラインレンダリングのほうが軽量です)。

ページ独自の dataHook はデータにすぎません。プレビューには、ページがレンダリングされるプロバイダーのツリーと ルート CSS も必要です。 .storybook/runtime.json から確認してください (ファイルがない場合は scripts/discover-runtime.py . --out .storybook/runtime.json を実行します)。 providers[]、rootCss、portals[]、network.needsMsw は sb-setup によって共有プレビューで一度だけ設定されるため、 ページのストーリーで再接続が必要になることはほとんどありません。スクリプトがすでに .storybook/*.json に書き出した内容を、シェルスキャンで再導出してはいけません。フィールドを参照してください。

バッチ(複数のコンポーネント)

コンポーネントごとにストーリーを 1 つ作成し(実際の状態だけをカバーします)、その後、 scripts/validate-stories.sh で各ストーリーをゲートします。Claude Code では、Agent ツールを使って コンポーネントを並列に作成すれば、バッチ処理を高速化できます。ただし、作業内容は同じであり、 特別なサブエージェントは不要です。

完了前のゲート

SKILL=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
CORE=${CLAUDE_PLUGIN_ROOT:-${CLAUDE_PLUGIN_ROOT}}
"$CORE/scripts/validate-stories.sh" path/to/Foo.stories.tsx
# --strict adds tsc + eslint · --diff lints only changed stories
# For the "give me confidence" verdict (setup readiness preflight + conformance in one),
# run "$SKILL/scripts/check-story-ready.sh" path/to/Foo.stories.tsx instead — CONFIDENT when discovery JSONs are present.

FAIL があるとゼロ以外のステータスで終了します。次に進む前に修正してください。play を記述した場合は、 判定用サブエージェントも実行してください(references/validate-workflow.md を参照)。play に意味があるかどうかは bash では検証できません。ストーリーをエージェントが実行できる CLI ゲート(ヘッドレス vitest + a11y)にする方法は、 references/test-wiring.md を参照してください。

コメント