デザインシステム
3つの段階で同じ専門知識を提供します。オーケストレーターは mode を明示的に渡します。
| モード | タイミング | 質問 |
|---|---|---|
| PLAN | フィーチャー開発フェーズ2 | このフィーチャーはどのパターン/抽象化を使うべきか? |
| BUILD | フィーチャー開発フェーズ4 | PLANの決定を実装中に適用する。 |
| REVIEW | フィーチャー開発フェーズ5 | 実装は実際にそれらに従っているか? |
モードが未指定でブランチ差分が存在する場合は、デフォルトで REVIEW を使用します。 モードが未指定で差分がまだない場合は、デフォルトで PLAN を使用します。
PLANモード
コードが存在する前の段階。入力: 要件定義書、Figmaノードまたはスクリーンショット、スコープ内のルート。
- pattern-library(
src/index.ts、src/theme.ts、src/core/)と app-pro-ui を検索し、類似のフィーチャーを探す。 - デザインの主要なUI要素ごとに抽象化テスト(下記)を実行する。
- 各要素について: ローカルに残す | 既存PL APIを使用 | トークン/バリアントを使用 | PL PRが必要 — パスを明記して記載する。
- PLの順序付け(PL PRをapp-pro-uiの前/並行して行う)と、欠落しているコピー/アセットをフラグする。
UIサーフェスがない場合: 1行で「Not applicable (no UI)」を返す。
出力: # Design system (PLAN): [feature] — 再利用リスト、将来の変更、順序付け。ブランチ差分は不要。
BUILDモード
実装中。入力: デザインシステムPLANの出力、編集中のファイル。
- PLANの決定を適用する: 名前付きPLコンポーネント/トークンを使用する。ローカルに残す指定を尊重する。
- 下記の推論レイヤーに従う — 再利用可能な見た目をフィーチャーコード内で再現しない。
- コーディング中に学んだことでPLANが間違っている場合は、ビルドサマリーに逸脱を文書化する。静かに逸脱しない。
出力: 逸脱がない限り不要 — 逸脱がある場合はビルドサマリーに記載する。
REVIEWモード
実装後。このブランチ(app-pro-ui または pattern-library)をスキャンし、デザインシステムに存在すべきUIの決定事項を探す。「スタイルを削除」や「共有コンポーネントを使用」とだけ言わない。任意のフィーチャーが同じことをできるようにするための、最小のグローバルなpattern-libraryの変更を推奨する。または、抽象化が正当化されない場合はローカル実装を残すことを推奨する。
これは「すべてのスタイルがpattern-libraryに属する」という意味ではない。繰り返される製品/UXの決定は、個々のビルダーが再発明しないように、徐々にシステムにエンコードされるべきである。フィーチャーコードは依然としてローカルに構成してもよい。
アーキテクチャルール: 再利用可能な視覚的決定はpattern-libraryに属する。フィーチャーコードは純粋にローカルなレイアウト/構成に sx を使用してもよいが、再利用可能なコンポーネントのスタイリング、トークン、状態、インタラクションパターンを再現してはならない。確立されたPL/MUI APIが存在する場合は、style、カスタムCSS、レガシーなMUIシステムプロップを避ける。
このスキルはDSレイヤーである。app-pro-uiのフック/ユーティリティ/グリッド構造や一般的なコード衛生については、refactoring スキルを使用する。
推論レイヤー
すべての発見事項を以下のルールで判断する。これらは長年にわたるpattern-libraryとapp-pro-uiのレビューコメントに基づく。新しいAPIよりも既存のAPIを優先する。コードをpattern-libraryに移動することが自動的に改善になるわけではない。
抽象化テスト
候補となるレシピ、トークン、新しいAPIごとにこれを実行する。これが主要な判断基準であり、検出は候補を生成するだけである。
- これはローカルな構成か?
- 同じレシピが他に出現するか?
- そのコンポーネントがもともとこれを所有するはずか?
- pattern-libraryに移動することで、意味のある将来の決定が減るか?
- APIを追加することで、実際にpattern-libraryが悪化するか?
類似性だけでは抽象化を正当化できない。似たように見える2つのスニペットが、異なる製品コンセプトを表現している場合がある。同じ製品/UXの決定が一緒に進化すべき場合には、共有抽象化を優先する。
sx は問題ではない。問題はデザイン決定がどこに存在するかである。テーマトークンを使用した sx は16進数より優れている。繰り返されるレシピはpattern-libraryに属するかもしれない。単発の <Stack sx={{ mt: 2 }}> は通常属さない。テストがローカルな解決策が正しいと示す場合は、発見事項からそれを除外する — Lowとしてリストしない。
1. デザインシステムを使用する — フィーチャーで再利用可能な決定を再スタイリングしない
- 確立されたpattern-libraryコンポーネントを再利用可能な製品パターンに使用する(
CardWithAction(アクションがなくても)、複合カードとしてのCardCTAFeatured、DetailPanelToggle)。これらを生のCardから再構築しない。 - レイアウトがローカルな場合は、カスタムレイアウトCSSよりも
Stack/GridのようなMUI構成プリミティブを優先する。 - ローカルなジオメトリを発明する前に、確立されたレイアウトプリミティブとデフォルトを使用する。
- 再利用可能な色、シャドウ、マーケティング/AI処理は、
pattern-library/src/theme.tsにパレット形状のトークン(primary.main、ai.gradient.start)として配置する。値が製品上の決定である場合、ハードコードされた16進数、塗りつぶし、シャドウよりもトークンやtheme.shadowsを優先する。 - 非推奨のMUIスタイルasプロップではなく、
sxを使用する。それを回避するために共有コンポーネントにスタイル名のプロップを追加しない。ローカルなsxは、構成であり再利用可能な見た目でない場合は問題ない。 - フィーチャーが他のサーフェスと共有する新しい見た目(注目メディア、展開オーバーレイ、反転/マーケティングサーフェス)を必要とする場合は、pattern-libraryにパターンまたはプロップを追加する。
2. 共有コンポーネントをジェネリックに保つ
- フィーチャー固有のパディング、サイドナビ、チャートの変更を共有の
Card、PageSection、またはパブリックなindex.tsエクスポートに追加しない。プロトタイプのスコープを設定し、無関係なファイルを元に戻す。変更するのはアイテムであって、クロームではない。アイテムだけが間違っている場合。 - プロップには再利用を見込んだ名前を付ける(
footerDescription、単一フィーチャーのラベルではない)。追加の動作はオプションにする(テキストエリアの行番号、カンマ)。 - フォークされたJSX(
variant === "marketing"チェック)よりもテーマバリアントとStorybookのargsを優先する。 - アプリが消費しない場合は、チャートやその他の内部要素をpattern-libraryからエクスポートしない。
- 長期的には、すべてのページに単発の視覚プロップを通す代わりに、サーフェスをテーマでラップする(例:マーケティング)。
3. エッジのビジュアルQA
- 角丸、等身のカード、はみ出た折り返しテキスト、モバイルFAB折りたたみ、ドロワー/モーダルとのz-index、コントロールが白背景で動作するかを確認する。
- 特別なスペーシングが必要か、デフォルトスタイルが他のモーダル/ページと既に一致しているかを問う。ずれた隣接要素に合わせるために、共有ヘッダーにパディングを追加しない — 隣接要素を修正する。
4. デザイン要件を疑問視する
異常なデザインをサポートするためにDS機能を追加する前に、デザイン自体が確立されたシステム動作に準拠すべきかどうかを判断する。疑わしい単発要件をエンコードするためだけにデザインシステムを拡張しない。
5. 不要なAPIサーフェスに抵抗する
提案されたDS抽象化はすべて、それが追加するAPIサーフェスを正当化しなければならない。コードをpattern-libraryに移動することは自動的に改善ではない。エクスペリエンスを向上させない構成は、メンテナンスコストである。
DSアーキテクチャの衛生だけを保つ:構成を妨げる不要なラッパー、重複するスタイリング、コンポーネントAPIの複雑さ、共有プリミティブ内のフィーチャー固有ロジック。Stack/sx の構成を妨げる場合は、ネストされた Box をフラット化する。単純なトークンには useTheme の代わりにテーマのショートハンド(background.main)を使用する。
6. 関連するサーフェスと一緒に出荷する
- アプリが消費する必要があるpattern-libraryの変更には、対応するapp-pro-uiまたはmoz-uiのPRと、それを検証する方法(amplify/domainなど)が必要である。
- バンプ方法を推奨する前に、消費側リポジトリの現在のパッケージ/バージョン規約(
package.json、lockfile、またはインストールドキュメント)を確認する。ピンスタイルを推測しない。 - 消費側アプリのPRが準備できるまで、共有プリミティブをマージしない。
起動時(REVIEWモード)
以下をコピーして追跡する:
レビューの進捗:
- [ ] このブランチをマージベースと差分する
- [ ] 候補を収集する(結論ではなく)
- [ ] 意図ごとにクラスタリングする(同じ決定、同じコードではない)
- [ ] 抽象化テストを実行する
- [ ] pattern-libraryを検索して既存の配置場所を探す
- [ ] 最小の変更を推奨する — ローカルに残す/DS変更なしを含む
- [ ] 発見事項を報告する。依頼がない限り実装しない
発見作業は必須ではない。差分が適切にローカルである場合は、そう述べて停止する。
ステップ1: ブランチをスキャンする
このブランチとそのマージベースを検査する。デフォルトブランチを検出する(git symbolic-ref refs/remotes/origin/HEAD または origin/main、次に main)。変更のあるリポジトリ(app-pro-ui または pattern-library)から実行する。
DEFAULT=$(git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's@^refs/remotes/@@')
DEFAULT=${DEFAULT:-origin/main}
git merge-base "$DEFAULT" HEAD
git diff $(git merge-base "$DEFAULT" HEAD)...HEAD -- '*.tsx' '*.ts' '*.jsx' '*.js' '*.css' '*.scss'
git diff --name-only $(git merge-base "$DEFAULT" HEAD)...HEAD
追加された行から候補を検索する:
スタイリング
style=sx=styled(css`/css(makeStyles/createStyles/withStyles- ハードコードされた
#hex、rgb(、rgba(、px(調査する、自動分類しない) - レガシーBoxプロップ:
display=、alignItems=、justifyContent=、flexDirection=
再発明または逸脱したUI
- 確立されたカードパターン(
CardWithAction、CardCTAFeatured)が適合するのに生のCardを使用 DetailPanelToggleの代わりにカスタム展開コントロールStack/Gridでローカルに構成できるのにカスタムレイアウトCSS- レイアウトプリミティブまたはデフォルトが既に幅を設定しているのに発明されたページジオメトリ
- シャドウが共有の見た目である場合に
theme.shadowsの代わりにハードコードされたシャドウ - 単一フィーチャーにのみ役立つ新しいパブリックエクスポートまたはテーマ編集
その後、各ヒットを開き、周囲のJSXを意図を読んで理解する。また、JSXの前に割り当てられた sx オブジェクト、<style> タグ、インポートされたスタイルシートもキャッチする。
.cursor/、node_modules/、.next/ は無視する。フィーチャーコード、共有 components/、Storybook、src/theme.ts を含める。
ステップ2: 検出、そして判断
検出はヒューリスティックである。分類は抽象化テストの後に行われる。
| 検出器 | 扱い | 例 |
|---|---|---|
style= / styled( / css / 新しい .css | 候補リーク | <Card style={{ flexBasis: "50%" }}> |
| デザインシステムの決定をエンコードしているように見えるハードコードされた視覚値、特に色、スペーシング、タイポグラフィ、半径、シャドウ、繰り返される寸法 | 候補トークン | color: "#002F50"; リークとして扱う前に px を調査する |
テーマキーを使用した sx={{ ... }} | 候補レシピ | sx={{ mt: 3, width: "100%" }} |
| レガシーBoxシステムプロップ | 候補レガシー | <Box display="flex" alignItems="center"> |
| 未使用の既存PLコンポーネント | 候補既存システム解決策 | テーブルが CardWithAction でラップされていない |
| 共有コンポーネントに対するフィーチャー固有の編集 | 候補スコープリーク | 一つのストーリーに合わせるための CardHeader のパディング |
| 単一フィーチャーのプロップまたはエクスポート | 候補非ジェネリックAPI | フィーチャー名のフッタープロップ、未使用のチャートのエクスポート |
ハードコードされた値を分類する前に調査する。正当なローカルケースには、計算された寸法、チャートジオメトリ、アイコン/キャンバス内部、境界線、仮想化レイアウト、固有のコンポーネント制約が含まれる。
最後の手段の例外(理由を文書化する。プリミティブを発明しない):
- pattern-libraryのプロップを使用できないサードパーティ/キャンバス/チャート内部
- 既存のレポートプリミティブがなく、本当に単発の印刷/PDFレイアウト
- pattern-libraryからエクスポートされないプロトタイプ専用ファイル
抽象化テストをローカル構成として通過した候補は、発見事項ではない。ギャップと誤認されそうな場合にのみ、昇格しない の下にそれらを配置する。それ以外の場合は省略する。
ステップ3: 意図ごとにクラスタリングする
同じ決定を表現するヒットをグループ化する。同じCSSや似たマークアップではない。
典型的な意図: 色/強調、スペーシング/アライメントレシピ、タイポグラフィ、コンポーネントクローム、インタラクション状態、フィーチャーパターン(バナー、ページヘッダー、カードCTA、ステータス)、ジェネリック vs 単一フィーチャーAPI、プロトタイプスコープ、疑わしいデザイン要件。
1つのクラスタ → 1つの推奨。同じ発見事項のいくつかのマイナーバリエーションよりも、1つの強力な推奨を優先する。
ステップ4: 最初にpattern-libraryを検索する
新しいものを提案する前に、兄弟の pattern-library リポジトリを検索する。パスを引用する。
- パブリックエクスポート —
pattern-library/src/index.ts - トークンとグローバルデフォルト —
pattern-library/src/theme.ts pattern-library/src/core/の下のコンポーネントプロップ/バリアント- リークを既に回避している同じコンポーネントの既存のapp-pro-ui使用法
UIをDSに吸収するための先例(これらを引用する。内部をapp-pro-uiにコピーしない):
- セマンティックプロップ:
TypographylineClamp—pattern-library/src/core/Typography/Typography.tsx - セマンティックプロップ:
ButtonaiGlow—pattern-library/src/core/Button/Button.t
...