ponshu-room-lite/docs/DARK_MODE_COLOR_GUIDELINES.md

7.9 KiB
Raw Blame History

Dark Mode色使用ガイドライン

🎯 目的

このガイドラインは、Dark Mode対応を自動化し、手動の条件分岐を完全に排除することで、以下を実現します:

  1. すべての画面で一貫したDark Mode体験
  2. 新機能追加時にDark Mode問題が発生しない
  3. メンテナンスコストの削減
  4. 個性のある配色(白だらけにならない)

絶対にやってはいけないこと

1. ハードコード色の使用

// ❌ NG: ハードコード
Icon(LucideIcons.star, color: Colors.blue)
Icon(LucideIcons.star, color: Color(0xFF376495))
Container(color: Colors.white)

2. 手動Dark Mode条件分岐

// ❌ NG: 手動条件分岐
final isDark = Theme.of(context).brightness == Brightness.dark;
color: isDark ? Colors.white : Colors.black

// ❌ NG: Theme.of(context).brightnessの直接使用
color: Theme.of(context).brightness == Brightness.dark ? Colors.grey[400] : null

3. Theme.of(context).primaryColorの直接使用

// ❌ NG: primaryColorは内部でDark/Light切り替えが必要
Icon(LucideIcons.star, color: Theme.of(context).primaryColor)

正しい使い方

Material 3 ColorSchemeを使う

Flutter Material 3は、Dark/Light両モードに自動対応するセマンティックカラーを提供しています。

基本パターン

// ✅ 正しい: ColorSchemeを使う
Theme.of(context).colorScheme.primary     // メインブランドカラー
Theme.of(context).colorScheme.secondary   // アクセントカラー
Theme.of(context).colorScheme.onSurface   // 一般的なアイコン/テキスト
Theme.of(context).colorScheme.surface     // 背景色
Theme.of(context).colorScheme.error       // エラー色

📘 用途別カラー選択ガイド

用途 使用するカラー Dark Mode Light Mode
見出し・セクションヘッダー colorScheme.secondary オレンジ #FFB74D 濃いオレンジ #FF6F00 ガイド画面「レベルと称号」
重要なボタン colorScheme.primary 明るい青 #8AB4F8 ポシマイブルー #376495 FAB、プライマリボタン
一般的なアイコン colorScheme.onSurface 白/グレー(自動) 黒/グレー(自動) リスト項目のアイコン
一般的なテキスト textTheme.bodyMedium 白(自動) 黒(自動) 本文テキスト
強調テキスト colorScheme.primary 明るい青 ポシマイブルー リンク、強調部分
エラーメッセージ colorScheme.error 赤(自動調整) 赤(自動調整) エラー表示
背景色 colorScheme.surface ダークグレー #1E1E1E カード、ダイアログ
半透明背景 colorScheme.primary.withValues(alpha: 0.1) 自動調整 自動調整 チップ、バッジ背景

🔧 実装例

アイコン

// セクションヘッダー(アクセントカラー)
Icon(LucideIcons.trophy, color: Theme.of(context).colorScheme.secondary)

// 一般的なアイコン
Icon(LucideIcons.user, color: Theme.of(context).colorScheme.onSurface)

// 重要なアイコン
Icon(LucideIcons.sparkles, color: Theme.of(context).colorScheme.primary)

テキスト

// 見出しTheme準拠
Text(
  '見出し',
  style: Theme.of(context).textTheme.titleMedium?.copyWith(
    fontWeight: FontWeight.bold,
  ),
)

// 強調テキスト(プライマリカラー)
Text(
  '重要',
  style: Theme.of(context).textTheme.bodyLarge?.copyWith(
    color: Theme.of(context).colorScheme.primary,
  ),
)

// アクセント見出し(セカンダリカラー)
Text(
  'セクション名',
  style: Theme.of(context).textTheme.titleMedium?.copyWith(
    color: Theme.of(context).colorScheme.secondary,
    fontWeight: FontWeight.bold,
  ),
)

背景色

// カード背景
Container(
  color: Theme.of(context).colorScheme.surface,
  child: ...,
)

// 半透明背景(ブランドカラー)
Container(
  color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
  child: ...,
)

ボタン

// プライマリボタン
ElevatedButton(
  onPressed: () {},
  style: ElevatedButton.styleFrom(
    backgroundColor: Theme.of(context).colorScheme.primary,
    foregroundColor: Theme.of(context).colorScheme.onPrimary,
  ),
  child: Text('保存'),
)

// セカンダリボタン(アクセント)
ElevatedButton(
  onPressed: () {},
  style: ElevatedButton.styleFrom(
    backgroundColor: Theme.of(context).colorScheme.secondary,
    foregroundColor: Theme.of(context).colorScheme.onSecondary,
  ),
  child: Text('アクション'),
)

🚨 特殊ケース(例外)

エラー・警告・成功(セマンティックカラー)

一部の色は意味が固定されているため、ハードコードが許可されます:

// ✅ OK: エラーは常に赤
Icon(LucideIcons.alertTriangle, color: Colors.red)

// ✅ OK: 成功は常に緑
Icon(LucideIcons.checkCircle, color: Colors.green)

// ✅ OK: 警告は常にオレンジ
Icon(LucideIcons.info, color: Colors.orange)

ただし、可能な限り colorScheme.error を使用してください:

// ✅ より良い: Material 3のエラーカラー
Icon(LucideIcons.alertTriangle, color: Theme.of(context).colorScheme.error)

🔍 既存コードの修正方法

パターン1: primaryColor → colorScheme.primary

// Before ❌
Icon(LucideIcons.star, color: Theme.of(context).primaryColor)

// After ✅
Icon(LucideIcons.star, color: Theme.of(context).colorScheme.primary)

パターン2: 手動条件分岐 → colorScheme.onSurface

// Before ❌
final isDark = Theme.of(context).brightness == Brightness.dark;
Icon(LucideIcons.user, color: isDark ? Colors.grey[400] : null)

// After ✅
Icon(LucideIcons.user, color: Theme.of(context).colorScheme.onSurface)

パターン3: セクションヘッダー → colorScheme.secondary

// Before ❌
Icon(LucideIcons.trophy, color: Theme.of(context).primaryColor)
Text('見出し', style: TextStyle(color: Theme.of(context).primaryColor))

// After ✅(アクセントカラーで目立たせる)
Icon(LucideIcons.trophy, color: Theme.of(context).colorScheme.secondary)
Text('見出し', style: Theme.of(context).textTheme.titleMedium?.copyWith(
  color: Theme.of(context).colorScheme.secondary,
))

📦 ColorScheme定義app_theme.dart

現在のカラースキーム:

Light Mode

  • primary: ポシマイブルー #376495
  • secondary: 濃いオレンジ #FF6F00
  • surface: 白 #FFFFFF
  • onPrimary: 白(自動計算)
  • onSecondary: 白(自動計算)
  • onSurface: 黒(自動計算)

Dark Mode

  • primary: 明るい青 #8AB4F8
  • secondary: 温かいオレンジ #FFB74D
  • surface: ダークグレー #1E1E1E
  • onPrimary: 黒(自動計算)
  • onSecondary: 黒(自動計算)
  • onSurface: 白(自動計算)

チェックリスト

新しい画面/ウィジェットを作成する際は、以下を確認してください:

  • ハードコード色を使っていない(Colors.blue, Color(0xFF...) など)
  • brightness == Brightness.dark の条件分岐を使っていない
  • Theme.of(context).primaryColor の代わりに colorScheme.primary を使用
  • アイコンは colorScheme.secondary または colorScheme.onSurface
  • テキストは textTheme.xxx を使用
  • 背景は colorScheme.surface を使用

🔗 参考資料


最終更新: 2026-01-21 作成者: Claude (Antigravity AI)