ponshu-room-lite/docs/DARK_MODE_GUIDELINES.md

199 lines
6.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ダークモード視認性ガイドライン
## 目的
ダークモード実装時に「背景と同化して見えない」問題を防ぐための開発ガイドラインです。
## 基本原則
### 1. **色の明示的指定**
**NG**: `Theme.of(context).primaryColor` をダークモードで直接使用
```dart
// NG例: ダークモードでは #8AB4F6 になり、暗い背景で見えにくい
color: Theme.of(context).primaryColor
```
**OK**: brightness チェックで明示的に明るい色を指定
```dart
// 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
```dart
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フィルタチップ
```dart
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
```dart
ElevatedButton(
style: ElevatedButton.styleFrom(
// ダークモードでも見えるよう固定色を使用
backgroundColor: AppTheme.posimaiBlue, // #376495
foregroundColor: Colors.white,
),
child: const Text('確認'),
)
```
#### SnackBar
```dart
SnackBar(
content: Text(
'メッセージ',
style: TextStyle(
color: isDark ? Colors.white : Colors.white, // 明示的に白を指定
),
),
backgroundColor: isDark
? const Color(0xFF2C2C2C) // ダーク背景
: Colors.grey[850],
behavior: SnackBarBehavior.floating,
)
```
#### バッジカウンター
```dart
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** 以上
推奨ツール:
- [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)
- [Coolors Contrast Checker](https://coolors.co/contrast-checker)
## 実装例リファレンス
実装済みファイル:
- `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