ponshu-room-lite/docs/DARK_MODE_GUIDELINES.md

6.6 KiB
Raw Blame History

ダークモード視認性ガイドライン

目的

ダークモード実装時に「背景と同化して見えない」問題を防ぐための開発ガイドラインです。

基本原則

1. 色の明示的指定

NG: Theme.of(context).primaryColor をダークモードで直接使用

// NG例: ダークモードでは #8AB4F6 になり、暗い背景で見えにくい
color: Theme.of(context).primaryColor

OK: brightness チェックで明示的に明るい色を指定

// OK例: ダークモードでは明るい青 (#64B5F6) を使用
color: Theme.of(context).brightness == Brightness.dark
    ? const Color(0xFF64B5F6)  // より明るい青
    : Theme.of(context).primaryColor  // #376495

2. 推奨カラーパレット

アクセント色選択状態、重要なUI要素

用途 ライトモード ダークモード
プライマリ(通常) #376495 (AppTheme.posimaiBlue) #64B5F6 (明るい青)
プライマリ(強調) AppTheme.posimaiBlue #8AB4F6 (Theme.primaryColor)
チェックマーク Theme.primaryColor #64B5F6
選択中チップ AppTheme.posimaiBlue colorScheme.primary (#8AB4F6)

テキスト色

用途 ライトモード ダークモード
本文 Colors.black87 Colors.white
副見出し Colors.grey[600] Colors.grey[300]
薄い表示 Colors.grey[400] Colors.grey[500]

背景・ボーダー

用途 ライトモード ダークモード
カード背景 Colors.white #1E1E1E
ダイアログ背景 Colors.white #2C2C2C
ボーダー(通常) Colors.grey[300] Colors.grey[700]
ボーダー(強調) Colors.grey[400] Colors.grey[600]

3. コンポーネント別パターン

ダイアログ選択肢SimpleDialogOption

Icon(
  isSelected ? Icons.check : Icons.circle_outlined,
  color: isSelected
      ? (Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6)  // ダークモード用の明るい青
          : Theme.of(context).primaryColor)
      : Colors.grey[400],
)

FilterChipフィルタチップ

FilterChip(
  selected: isSelected,
  selectedColor: Theme.of(context).brightness == Brightness.dark
      ? colorScheme.primary  // #8AB4F6
      : AppTheme.posimaiBlue,
  side: isSelected
      ? BorderSide(
          color: Theme.of(context).brightness == Brightness.dark
              ? colorScheme.primary
              : AppTheme.posimaiBlue,
          width: 1.5,
        )
      : null,
  // 非選択時の明示的なスタイル指定
  backgroundColor: isDark
      ? Colors.grey[800]?.withValues(alpha: 0.5)
      : null,
  side: BorderSide(
    color: isDark
        ? Colors.grey[700]!
        : colorScheme.outline.withValues(alpha: 0.5),
  ),
)

ボタンAlertDialog内のElevatedButton

ElevatedButton(
  style: ElevatedButton.styleFrom(
    // ダークモードでも見えるよう固定色を使用
    backgroundColor: AppTheme.posimaiBlue,  // #376495
    foregroundColor: Colors.white,
  ),
  child: const Text('確認'),
)

SnackBar

SnackBar(
  content: Text(
    'メッセージ',
    style: TextStyle(
      color: isDark ? Colors.white : Colors.white,  // 明示的に白を指定
    ),
  ),
  backgroundColor: isDark
      ? const Color(0xFF2C2C2C)  // ダーク背景
      : Colors.grey[850],
  behavior: SnackBarBehavior.floating,
)

バッジカウンター

Container(
  decoration: BoxDecoration(
    color: Theme.of(context).brightness == Brightness.dark
        ? const Color(0xFF64B5F6).withValues(alpha: 0.15)
        : Theme.of(context).primaryColor.withValues(alpha: 0.1),
    border: Border.all(
      color: Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6).withValues(alpha: 0.4)
          : Theme.of(context).primaryColor.withValues(alpha: 0.3),
    ),
  ),
  child: Text(
    '2 / 3',
    style: TextStyle(
      color: Theme.of(context).brightness == Brightness.dark
          ? const Color(0xFF64B5F6)
          : Theme.of(context).primaryColor,
    ),
  ),
)

開発時のチェックリスト

新機能実装時

  • ライトモードで表示確認
  • ダークモードで表示確認(必須)
  • 以下の要素が見えるか確認:
    • テキスト(タイトル、本文、ラベル)
    • アイコン(選択状態、非選択状態)
    • ボーダー・区切り線
    • ボタン(通常、選択、無効)
    • カウンター・バッジ表示

コードレビュー時

  • Theme.of(context).primaryColor の使用箇所でbrightness チェックがあるか
  • const TextStyle() に明示的な color 指定があるか
  • Colors.grey のような曖昧な色ではなく、明示的な階調(Colors.grey[300]等)を使用しているか

よくある問題と解決策

問題1: チェックマークが見えない

原因: Theme.of(context).primaryColor がダークモードで薄くなる 解決: 明示的に #64B5F6 を指定

問題2: バッジカウンターが見えない

原因: 背景色とテキスト色のコントラストが不足 解決: ダークモード用に明るい色 (#64B5F6) とアルファ値を調整した背景を使用

問題3: ボタンが見えない

原因: Theme.of(context).primaryColor が背景と同化 解決: 固定色 AppTheme.posimaiBlue (#376495) を使用

問題4: SnackBarメッセージが読めない

原因: テキスト色が明示されておらず、デフォルトが暗い色になる 解決: color: Colors.white を明示的に指定

色のコントラスト比基準

WCAG 2.1 AA基準最低限:

  • 通常テキスト: 4.5:1 以上
  • 大きいテキスト18pt以上、14pt太字以上: 3:1 以上

推奨ツール:

実装例リファレンス

実装済みファイル:

  • lib/screens/soul_screen.dart: ダイアログチェックマーク
  • lib/widgets/gamification/badge_case.dart: バッジカウンター
  • lib/widgets/settings/backup_settings_section.dart: ダイアログボタン
  • lib/screens/camera_screen.dart: SnackBarメッセージ
  • lib/widgets/home/sake_filter_chips.dart: フィルタチップ

更新日: 2026-01-18 バージョン: 1.0