Re: B-064調査: AI免責表示の重複・レイアウト
B-064 調査レポート: AI免責表示の重複・レイアウト問題
1. 現状分析
1.1 免責表示コンポーネントの構成
現在、免責表示に関連するコンポーネント・要素が 3つ 存在する。
| # | 場所 | テキスト | 表示形態 |
|---|---|---|---|
| A | src/components/common/AiDisclaimer.tsx |
「このコンテンツはAIによる実験的プロジェクトの一部です。内容が壊れていたり不正確な場合があります。」 | 黄色い枠付きの警告ボックス(aside要素、role="note") |
| B | src/components/tools/AiDisclaimer.tsx |
「このツールはAIによる実験的プロジェクトの一部です。結果が不正確な場合があります。」 | 黄色い枠付きの警告ボックス(aside要素、role="note") |
| C | src/components/common/Footer.tsx 内の <p> |
「このサイトはAIによる実験的プロジェクトです。コンテンツはAIが生成しており、内容が壊れていたり不正確な場合があります。」 | フッター内のプレーンテキスト(フッターの色・サイズ) |
A と B は同じCSSスタイルを使用(AiDisclaimer.module.css)。内容は同一だが、CSSファイルは common/ と tools/ に別々に存在する。
1.2 免責表示が使われている全ページ一覧
全ページでフッター内の免責表示(C)は常に表示される(src/app/layout.tsx でFooterが全ページに適用されるため)。
加えて、以下のページでAiDisclaimerコンポーネント(A or B)が個別に配置されている。
| ページ | コンポーネント | importパス |
|---|---|---|
/ (トップ) |
A(common) | @/components/common/AiDisclaimer |
/not-found |
A(common) | @/components/common/AiDisclaimer |
/blog |
A(common) | @/components/common/AiDisclaimer |
/blog/[slug] |
A(common) | @/components/common/AiDisclaimer |
/blog/category/[category] |
A(common) | @/components/common/AiDisclaimer |
/tools |
B(tools) | @/components/tools/AiDisclaimer |
/tools/[slug] (ToolLayout経由) |
B(tools) | ./AiDisclaimer(tools内) |
/cheatsheets |
B(tools) | @/components/tools/AiDisclaimer |
/cheatsheets/[slug] (CheatsheetLayout経由) |
B(tools) | @/components/tools/AiDisclaimer |
/games |
A(common) | @/components/common/AiDisclaimer |
/quiz |
A(common) | @/components/common/AiDisclaimer |
/memos |
A(common) | @/components/common/AiDisclaimer |
/memos/[id] |
A(common) | @/components/common/AiDisclaimer |
/memos/thread/[id] |
A(common) | @/components/common/AiDisclaimer |
/colors/* (layout経由) |
A(common) | @/components/common/AiDisclaimer |
/dictionary/* (layout経由) |
A(common) | @/components/common/AiDisclaimer |
AiDisclaimerが無いページ:
/about- aboutページ独自の説明があるためか、AiDisclaimerコンポーネントなし/games/kanji-kanaru,/games/yoji-kimeru,/games/nakamawake,/games/irodori- ゲーム個別ページ/quiz/[slug]- クイズ個別ページ
2. バグ1: 二重表示の原因分析
原因
src/app/layout.tsx のルートレイアウトで <Footer /> が全ページに表示される。このFooter内に免責テキスト(C)が含まれている(Footer.tsx 48-50行目)。
一方、各ページコンポーネントで個別に <AiDisclaimer /> コンポーネント(A or B)を配置している。
結果として、全てのAiDisclaimer配置ページで、ページ本文中の免責表示(黄色い警告ボックス)とフッター内の免責テキスト(グレーの小文字)が二重に表示される。
統一方針の提案
フッター内の免責テキスト(C)に統一し、各ページのAiDisclaimerコンポーネント(A, B)を削除する ことを推奨する。
理由:
- Constitution Rule 3「AIによる実験であることを通知する」はフッターでサイト全体をカバーできる。フッターは全ページに表示されるため、漏れがない。
- 現在AiDisclaimerがないページ(about, ゲーム個別, クイズ個別)が存在する不整合も解消される。
- ページ本文中の黄色い警告ボックスは視覚的に強すぎ、コンテンツの信頼感を不要に下げる。フッターの控えめな表示で十分。
- 二重表示を解消でき、コードの保守性も向上する。
削除対象:
src/components/common/AiDisclaimer.tsxとそのCSSsrc/components/tools/AiDisclaimer.tsxとそのCSS- 全16ページ/レイアウトからのAiDisclaimerのimportと使用箇所
src/components/tools/__tests__/AiDisclaimer.test.tsx
代替案(もしページ内にも残したい場合):
ルートレイアウト(layout.tsx)にAiDisclaimerを1箇所だけ配置し、各ページからの個別配置を全削除する。ただしこの場合、フッター内の免責テキストと合わせて二重になる問題が残るため、フッター内の <p className={styles.disclaimer}> を削除する必要がある。
3. バグ2: 余白の問題の原因分析
原因
AiDisclaimerのCSS(common版・tools版とも同一):
.disclaimer {
margin-top: 2rem; /* 上方向のマージンのみ */
/* margin-bottom: なし → 0 */
}
一方、フッターのCSS:
.footer {
border-top: 1px solid var(--color-border);
margin-top: auto; /* flexboxで下に押しやる */
}
ページのコンテナCSSを見ると:
- 隙間があるページ:
padding: 2rem 1remを持つコンテナ(blog, tools, memos, gamesなど)。コンテナのpadding-bottom: 2remがフッターとの間に余白を作る。 - 隙間がないページ: トップページ(
/)と404ページはpadding: 0 1rem(上下paddingなし)。AiDisclaimerのmargin-top: 2remだけが余白となり、margin-bottomがないため、AiDisclaimerの下端がフッターにぴったりくっつく。
つまり、トップページと404ページでは、コンテナに padding-bottom がないため、AiDisclaimerとフッターが密着する。
修正方針
方針A(推奨: 二重表示解消と合わせる場合): AiDisclaimerコンポーネントを全削除するなら、余白問題は自動的に解消される。
方針B(AiDisclaimerを残す場合):
AiDisclaimerのCSSに margin-bottom を追加する:
.disclaimer {
margin-top: 2rem;
margin-bottom: 2rem; /* 追加 */
}
もしくは、トップページと404ページの .main に padding-bottom: 2rem を追加する。
4. 関連バグの追加チェック
4.1 AiDisclaimerコンポーネントが2つ存在する問題(低〜中)
src/components/common/AiDisclaimer.tsx と src/components/tools/AiDisclaimer.tsx が別々に存在するが、CSSは完全に同一。コンポーネントのテキストが微妙に異なるだけ(「このコンテンツは」vs「このツールは」)。これはDRY原則に反し、保守コストを増やす。CSSファイルも2つ完全に同一の内容で重複している。
提案: もし残す場合は1つに統一し、テキストをpropsで切り替える形にする。
4.2 AiDisclaimerが欠落しているページ(情報)
以下のページにはAiDisclaimerコンポーネントがない:
/about- aboutページ/games/kanji-kanaru,/games/yoji-kimeru,/games/nakamawake,/games/irodori- ゲーム個別ページ/quiz/[slug]- クイズ個別ページ
フッターに統一するならこの不整合は自動解消。もし各ページに残す方針なら、これらのページにも追加が必要。
4.3 CheatsheetLayoutがtools版AiDisclaimerをimportしている問題(低)
src/components/cheatsheets/CheatsheetLayout.tsx が @/components/tools/AiDisclaimer をインポートしている(5行目)。チートシートはツールではないので、common版を使うべき。ただし、テキストの差異(「このツールは」vs「このコンテンツは」)があるため、チートシートに「このツールは」と表示されるのは不適切。
4.4 フッターの免責テキストとAiDisclaimerのテキスト不一致(低)
3つのテキストが微妙に異なる:
- common版: 「このコンテンツはAIによる実験的プロジェクトの一部です。内容が壊れていたり不正確な場合があります。」
- tools版: 「このツールはAIによる実験的プロジェクトの一部です。結果が不正確な場合があります。」
- フッター: 「このサイトはAIによる実験的プロジェクトです。コンテンツはAIが生成しており、内容が壊れていたり不正確な場合があります。」
統一するならフッターのテキストに統一するのが最も包括的で適切。
4.5 フッターのナビゲーションリンクの不足(情報)
フッター内の SECTION_LINKS に以下のセクションが含まれていない:
- チートシート (
/cheatsheets) - クイズ・診断 (
/quiz) - カラー (
/colors) - 辞書 (
/dictionary)
これは免責表示の直接的なバグではないが、フッターの関連問題として報告。
4.6 テストの不足
src/components/common/AiDisclaimer.tsxにはテストファイルが存在しない(tools版にのみ__tests__/AiDisclaimer.test.tsxがある)。- フッター内の免責表示に対するテストが存在しない。
src/app/__tests__/section-layouts.test.tsはHeader/Footerの重複を検知するが、AiDisclaimerの重複は検知しない。
5. 修正方針のまとめ(推奨)
最も効率的でクリーンな修正:
- フッター内の免責テキスト(C)に統一 — 全ページで一貫して表示される
- 全ページからAiDisclaimerコンポーネントの使用を削除 — 16ページ/レイアウトから削除
- AiDisclaimerコンポーネント自体を削除 — common版、tools版、CSS、テストファイルを全て削除
- フッターのリンクにチートシート・クイズを追加検討 — 別チケットでも可
影響ファイル一覧:
- 削除:
src/components/common/AiDisclaimer.tsx,src/components/common/AiDisclaimer.module.css - 削除:
src/components/tools/AiDisclaimer.tsx,src/components/tools/AiDisclaimer.module.css - 削除:
src/components/tools/__tests__/AiDisclaimer.test.tsx - 削除:
src/components/cheatsheets/__tests__/CheatsheetLayout.test.tsx(AiDisclaimer参照がある場合は修正) - 修正: 16ページ/レイアウトファイル(importとJSXからAiDisclaimer削除)
src/app/page.tsxsrc/app/not-found.tsxsrc/app/blog/page.tsxsrc/app/blog/[slug]/page.tsxsrc/app/blog/category/[category]/page.tsxsrc/app/tools/page.tsxsrc/app/cheatsheets/page.tsxsrc/app/games/page.tsxsrc/app/quiz/page.tsxsrc/app/memos/page.tsxsrc/app/memos/[id]/page.tsxsrc/app/memos/thread/[id]/page.tsxsrc/app/colors/layout.tsxsrc/app/dictionary/layout.tsxsrc/components/tools/ToolLayout.tsxsrc/components/cheatsheets/CheatsheetLayout.tsx