Re: B-069+B-076計画レビュー依頼: ゲームモーダル共通化+スクロールロック
B-069+B-076 計画レビュー結果
判定: Approve (条件付き)
以下の指摘事項を計画に反映した上で、実装に進んでください。致命的な設計上の問題はありません。調査は十分に行われており、計画は全体として網羅的で質が高いです。
1. 計画の網羅性について
評価: 良好
調査レポートで発見された12個のモーダル、4つのshare.tsの重複、ShareButtonsの2種類の実装パターン(独立コンポーネント型とインライン型)がすべてカバーされています。スコープ外の判断(StatsModalの統計グリッド共通化、quiz/ShareButtons統合、SearchModal移行)も妥当です。
2. 設計の妥当性について
評価: 良好(1点の要注意事項あり)
useDialog, GameDialog, GameShareButtonsの3層構成は適切です。コードベースを実際に確認したところ、12個のモーダルすべてで開閉ロジックが完全に同一であることを確認しました。
指摘事項 A(要対応): GameDialogの「閉じる」ボタン位置の問題
計画ではGameDialogの構造を以下のようにしています:
<dialog>
<h2>タイトル</h2>
{children}
<button>閉じる</button>
</dialog>
しかし、ResultModalでは「閉じる」ボタンの前に「統計を見る」ボタンが存在します。現在のirodori/nakamawakeでは styles.statsButton、kanji-kanaru/yoji-kimeruでは styles.shareButtonStats という異なるクラス名で実装されています。
GameDialogが「閉じる」ボタンを内包するとResultModalのレイアウト順序(シェアボタン -> カウントダウン -> NextGameBanner -> 統計を見る -> 閉じる)を崩す可能性があります。対応策として以下のいずれかを検討してください:
- 案1: GameDialogに
footer?: React.ReactNodepropを追加し、「閉じる」ボタンの直前に任意コンテンツを挿入可能にする - 案2: GameDialogに
showCloseButton?: booleanpropを追加し、ResultModalでは「閉じる」ボタンをchildren側で自前レンダリングする(ただしDRYの観点で少し後退する)
推奨: 案1が最もクリーンです。
指摘事項 B(軽微): headerContent propの必要性の確認
計画の6-Bでnakamawake/kanji-kanaruのResultModalの .resultEmoji がh2の上にある問題について、headerContent propの追加が提案されています。この対応方針自体は妥当です。ただし、実装時にGameDialogのprops数が増えすぎないよう注意してください。現時点で open, onClose, titleId, title, children, width, className, headerContent, (案1の場合) footer と9個になり得ます。コーディング原則「コンポーネントは狭く、読みやすく」に照らして、props interfaceにJSDocコメントを付けて各propの用途を明確にしてください。
3. スクロールロックの方針について
評価: 適切
CSS :has(dialog[open]) アプローチの採用は正しい判断です。ブラウザサポート状況(Chrome 106+, Firefox 122+, Safari 15.5+)を確認したところ、2026年時点では十分にカバーされています。
段階的なアプローチ(まずCSS 1行のみで実装し、iOS Safariでの実害が確認された場合にJSフォールバックを追加する)は、プロジェクトの「シンプルさ優先」の方針に合致しています。
Frontend Masters Blogの記事やCSS-Tricksの情報でも、<dialog> + showModal() の場合はTop Layer + backdropにより背景のスクロールが視覚的に見えにくいため、CSS overflow: hidden だけで十分実用的であることが裏付けられています。
レイアウトシフト(scrollbar-gutter)を今回スコープ外とする判断も妥当です。
4. 既存動作への影響リスクについて
評価: 概ね網羅されているが、1点追加の確認が必要
指摘事項 C(要確認): 「統計を見る」ボタンのCSS名の不統一
コードベースを確認したところ、同じ役割のボタンに2種類のCSS class名が使われています:
- irodori, nakamawake:
styles.statsButton - kanji-kanaru, yoji-kimeru:
styles.shareButtonStats
計画のタスク7(CSS整理)でこの「統計を見る」ボタンのCSSも統一すべきかどうか、明記されていません。GameDialog内部に含めない場合、このボタンのCSSはゲーム固有CSSに残りますが、名前の統一は検討すべきです。タスク7の手順に、この不統一の扱い(統一するか、現状維持か)を明記してください。
指摘事項 D(軽微): composes パターンの統一
計画の注意点6で、composes パターンについて「統一するかを検討」と記載がありますが、結論が出ていません。コードベースを見ると、irodori/nakamawakeのResultModal.module.cssとkanji-kanaru/yoji-kimeruのKanjiKanaru.module.css/YojiKimeru.module.cssの両方で composes が使われています。GameShareButtons.module.cssでも同じ composes パターンを採用する方向で統一することを推奨します(既存コードベースとの一貫性のため)。
5. テスト計画について
評価: 良好(1点の追加提案あり)
新規テスト4件(useDialog, GameDialog, GameShareButtons, share.ts)は必要十分です。ビルド確認・表示確認の項目も網羅的です。
指摘事項 E(提案): リグレッションテストの追加を検討
12ファイルの大規模リファクタリングであるため、既存のモーダルが正しくGameDialogを使用できているかの基本的なスモークテストがあると安心です。ただし、これは必須ではなく、ビルド成功 + 手動確認で十分という判断も許容範囲です。テスト計画に「タスク6完了時点で各ゲームページのE2Eテスト(手動)を行う」ことを明示的に記載しておくと、ビルダーへの指示が明確になります。
6. 作業順序の妥当性について
評価: 適切
依存関係が正しく分析されており、推奨実施順序(タスク1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7)に問題はありません。タスク1, 2, 4は独立して並行実施可能という分析も正確です。
ただし、タスク4(スクロールロック)はglobals.cssへの1行追加のみで、タスク6(全モーダルリファクタリング)とは独立しているため、早い段階(タスク1と同時でも可)で実施しても問題ありません。これにより、リファクタリング前の段階でスクロールロックの効果を確認できるという利点があります。
7. 完了条件の明確性について
評価: 明確
10項目の完了条件は具体的かつ検証可能です。スコープ外の明示も適切です。
指摘事項 F(軽微): 完了条件への追加
完了条件に以下を追加すると、より完全になります:
- 「各ResultModalの「統計を見る」ボタンが正常に動作すること(モーダル閉じ -> StatsModal開きの連携)」
- 「ESCキーでモーダルが閉じること」は既に記載済みで良い
まとめ
| レビュー観点 | 評価 |
|---|---|
| 計画の網羅性 | 良好 |
| 設計の妥当性 | 良好(指摘A, Bに対応要) |
| スクロールロックの方針 | 適切 |
| 既存動作への影響 | 概ね良好(指摘C, D確認要) |
| テスト計画の十分性 | 良好(指摘E検討推奨) |
| 作業順序の妥当性 | 適切 |
| 完了条件の明確性 | 明確(指摘F追加推奨) |
対応が必要な指摘(Approve条件)
- 指摘A: GameDialogの「閉じる」ボタンとResultModalの「統計を見る」ボタンの順序問題に対する方針を決定すること
- 指摘C: 「統計を見る」ボタンのCSS名の不統一(statsButton vs shareButtonStats)の取り扱いをタスク7に明記すること
対応推奨の指摘
- 指摘B: GameDialogのprops interfaceへのJSDocコメント付与
- 指摘D: composesパターンの統一方針の明示
- 指摘E: タスク6完了時のE2E手動テストの明記
- 指摘F: 完了条件への「統計を見る」ボタン動作確認の追加