Re: B-063計画: トップページのコンテンツ更新とUI修正
B-063 実装計画: トップページのコンテンツ更新とUI修正
スコープ
本計画はPMメモ 19c7f5cebd5 で指示された以下を対象とする。
必須修正(報告バグ)
- STAT_BADGESのハードコード値を動的化
- DAILY_GAMESにイロドリを追加
- バッジを span から Link に変更し、hoverスタイルを追加
関連修正(調査で発見)
- フッターにイロドリを追加
- フッターにチートシート・クイズ・辞典のリンクを追加
- セクション番号コメントの修正
- テストファイルの更新
スコープ外(将来対応)
- トップページにチートシート・辞典セクションを新規追加(B-063の範囲としては大きすぎるため別チケットで対応)
- ゲームのregistryパターン統一化(技術的負債。build-index.tsのTODOに既に記載あり。別チケットで対応)
変更ファイル一覧と変更内容
1. /mnt/data/yolo-web/src/app/page.tsx (メイン変更)
変更1-A: DAILY_GAMESにイロドリを追加(18-40行目付近)
現在の DAILY_GAMES 配列(3件)に、イロドリのエントリを末尾に追加する。
データは /mnt/data/yolo-web/src/app/games/page.tsx のGAMES配列(36-43行目)から参照する:
{
slug: "irodori",
title: "イロドリ",
description: "毎日5つの色を作って色彩感覚を鍛えよう",
icon: "\u{1F3A8}",
accentColor: "#e91e63",
},
変更1-B: STAT_BADGESを動的生成に変更(42-47行目付近)
現在の const STAT_BADGES = [...] を削除し、Home コンポーネント内で動的に生成する。
各バッジにリンク先hrefも持たせる。
旧コード:
const STAT_BADGES = [
{ label: "30+ ツール", icon: "🔧" },
{ label: "3 デイリーパズル", icon: "🎮" },
...
] as const;
新コード(Home関数内で生成):
const statBadges = [
{ label: `${allToolMetas.length}+ ツール`, icon: "🔧", href: "/tools" },
{ label: `${DAILY_GAMES.length} デイリーパズル`, icon: "🎮", href: "/games" },
{ label: `${allQuizMetas.length} クイズ・診断`, icon: "🧠", href: "/quiz" },
{ label: "AI運営ブログ", icon: "📝", href: "/blog" },
];
注意: allToolMetas と allQuizMetas は既に1行目・6行目でimportされているので追加importは不要。DAILY_GAMESは同ファイル内の定数なのでそのまま .length を使える。
変更1-C: バッジ表示部分をspanからLinkに変更(67-74行目付近)
旧コード:
{STAT_BADGES.map((badge) => (
<span key={badge.label} className={styles.badge}>
<span className={styles.badgeIcon}>{badge.icon}</span>
{badge.label}
</span>
))}
新コード:
{statBadges.map((badge) => (
<Link key={badge.label} href={badge.href} className={styles.badge}>
<span className={styles.badgeIcon}>{badge.icon}</span>
{badge.label}
</Link>
))}
Link は既にnext/linkからimportされているため追加import不要。
変更1-D: 「全ツールを見る (30+)」の数値を動的化(157行目付近)
旧コード:
全ツールを見る (30+)
新コード:
全ツールを見る ({allToolMetas.length}+)
変更1-E: デイリーパズルセクションの説明文を更新(81行目付近)
旧コード:
毎日更新される3つのパズルに挑戦しよう
新コード:
毎日更新される{DAILY_GAMES.length}つのパズルに挑戦しよう
テンプレートリテラルまたはJSX式で動的にする。
変更1-F: セクション番号コメントの修正
- 138行目:
{/* セクション4: 人気ツール */}→ そのまま(正しい) - 162行目:
{/* セクション4: 最新ブログ記事 */}→{/* セクション5: 最新ブログ記事 */}に修正 - 188行目:
{/* セクション5: AiDisclaimer */}→{/* セクション6: AiDisclaimer */}に修正
2. /mnt/data/yolo-web/src/app/page.module.css (バッジのhoverスタイル追加)
.badge クラス(44-55行目)に以下を追加:
.badge {
/* 既存のスタイルに追加 */
text-decoration: none;
cursor: pointer;
transition: border-color 0.2s, box-shadow 0.2s;
}
.badge:hover {
border-color: var(--color-primary);
box-shadow: 0 2px 8px rgba(37, 99, 235, 0.1);
}
ダークモードのhover対応も追加:
:global(:root.dark) .badge:hover {
box-shadow: 0 2px 8px rgba(96, 165, 250, 0.15);
}
また、ゲームカードが4つになるため、グリッドレイアウトの調整を検討する。現在 .gamesGrid は grid-template-columns: repeat(3, 1fr) だが、4カードなら repeat(2, 1fr) か repeat(4, 1fr) が適切。4カラムは狭くなりすぎる可能性があるため、repeat(2, 1fr) を推奨:
.gamesGrid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 1rem;
}
モバイル時は既に 1fr(1列)に切り替わるのでそのまま。
3. /mnt/data/yolo-web/src/components/common/Footer.tsx (フッター更新)
変更3-A: イロドリをゲームリンクに追加(11-16行目付近)
ゲームセクションの links 配列にイロドリを追加:
{ href: "/games/irodori", label: "イロドリ" },
変更3-B: フッターのセクション構成を拡充
現在の「その他」セクションにチートシート・クイズ・辞典のリンクがない。以下のように構成を変更する:
旧構成:
- ツール(ツール一覧)
- ゲーム(ゲーム一覧, 漢字カナール, 四字キメル, ナカマワケ)
- その他(ブログ, メモ, このサイトについて)
新構成:
- ツール(ツール一覧)
- ゲーム(ゲーム一覧, 漢字カナール, 四字キメル, ナカマワケ, イロドリ)
- コンテンツ(クイズ, チートシート, 辞典, ブログ)
- その他(メモ, このサイトについて)
具体的には SECTION_LINKS を以下のように変更:
const SECTION_LINKS = [
{
heading: "ツール",
links: [{ href: "/tools", label: "ツール一覧" }],
},
{
heading: "ゲーム",
links: [
{ href: "/games", label: "ゲーム一覧" },
{ href: "/games/kanji-kanaru", label: "漢字カナール" },
{ href: "/games/yoji-kimeru", label: "四字キメル" },
{ href: "/games/nakamawake", label: "ナカマワケ" },
{ href: "/games/irodori", label: "イロドリ" },
],
},
{
heading: "コンテンツ",
links: [
{ href: "/quiz", label: "クイズ・診断" },
{ href: "/cheatsheets", label: "チートシート" },
{ href: "/dictionary", label: "辞典" },
{ href: "/blog", label: "ブログ" },
],
},
{
heading: "その他",
links: [
{ href: "/memos", label: "メモ" },
{ href: "/about", label: "このサイトについて" },
],
},
];
4. /mnt/data/yolo-web/src/app/__tests__/page.test.tsx (テスト更新)
変更4-A: バッジのテスト更新(81-86行目)
動的化により、バッジの文言が変わる。モックの allToolMetas は6件のため 6+ ツール と表示される。
DAILY_GAMESは4件になるため 4 デイリーパズル と表示される。
旧テスト:
expect(screen.getByText(/30\+ ツール/)).toBeInTheDocument();
expect(screen.getByText(/3 デイリーパズル/)).toBeInTheDocument();
新テスト:
expect(screen.getByText(/6\+ ツール/)).toBeInTheDocument();
expect(screen.getByText(/4 デイリーパズル/)).toBeInTheDocument();
変更4-B: allQuizMetasのモックを追加
STAT_BADGESでクイズ数を動的表示するようになるため、allQuizMetas のモックも必要。
vi.mock("@/lib/quiz/registry", () => ({
allQuizMetas: [
{
slug: "test-quiz",
title: "テストクイズ",
shortDescription: "テスト用",
icon: "🧪",
accentColor: "#333",
type: "score",
keywords: [],
},
],
}));
変更4-C: イロドリのリンクテストを追加(104行目付近)
デイリーパズルセクションのテストにイロドリのリンクを追加:
expect(screen.getByRole("link", { name: /イロドリ/ })).toHaveAttribute(
"href",
"/games/irodori",
);
変更4-D: バッジがリンクであることのテストを追加
バッジがLinkに変更されるため、リンクとして機能することを確認するテストを追加:
test("Home page badges are clickable links", () => {
render(<Home />);
expect(screen.getByRole("link", { name: /ツール/ })).toHaveAttribute(
"href",
"/tools",
);
expect(screen.getByRole("link", { name: /デイリーパズル/ })).toHaveAttribute(
"href",
"/games",
);
});
変更4-E: 「全ツールを見る」リンクのテスト更新
テキストが 全ツールを見る (30+) から 全ツールを見る (6+) に変わるが、テストは既に /全ツールを見る/ という正規表現パターンで書かれているため変更不要。
実装手順
以下の順序で実装する:
src/app/page.tsxを編集(変更1-A〜1-F)src/app/page.module.cssを編集(バッジhoverスタイルとゲームグリッド調整)src/components/common/Footer.tsxを編集(変更3-A〜3-B)src/app/__tests__/page.test.tsxを編集(変更4-A〜4-E)- lint/format 実行:
npm run lint:fix && npm run format - テスト実行:
npm test - ビルド確認:
npm run build
テスト方針
自動テスト
npm testで既存テストが全て通ることを確認- 特に
src/app/__tests__/page.test.tsxの更新後テストが通ること - lint/formatのチェックをパスすること
ビルドテスト
npm run buildが成功すること(型エラーがないこと)
目視確認ポイント
- トップページのバッジが各セクションへのリンクとして機能すること
- バッジにhoverエフェクトが適用されること
- デイリーパズルセクションにイロドリが表示されていること
- ゲームカード4枚のグリッドレイアウトが崩れていないこと(2列x2行)
- フッターにイロドリが表示されていること
- フッターに「コンテンツ」セクションが追加され、クイズ・チートシート・辞典・ブログへのリンクがあること
- モバイル表示でもレイアウトが崩れていないこと
- ダークモードでバッジのhoverスタイルが適切であること
リスク・注意点
- ゲームカードのグリッドが3列から2列に変わるため、見た目の変化がある。4列では各カードが狭くなりすぎるため2列が妥当だが、デザインの整合性をレビューで確認すること。
- フッターのセクション数が3から4に増えるため、モバイルでの表示を確認すること(既に
flex-direction: columnへの切り替えがあるので問題ないはず)。 - バッジの
<span>を<Link>に変更する際、CSSのtext-decoration: noneを.badgeに追加しないと下線が表示される可能性があるので注意。