ponshu-room-lite/docs/DARK_MODE_COLOR_GUIDELINES.md

274 lines
7.9 KiB
Markdown
Raw Permalink Normal View History

# Dark Mode色使用ガイドライン
## 🎯 目的
このガイドラインは、Dark Mode対応を**自動化**し、手動の条件分岐を**完全に排除**することで、以下を実現します:
1. ✅ すべての画面で一貫したDark Mode体験
2. ✅ 新機能追加時にDark Mode問題が発生しない
3. ✅ メンテナンスコストの削減
4. ✅ 個性のある配色(白だらけにならない)
---
## ❌ 絶対にやってはいけないこと
### 1. ハードコード色の使用
```dart
// ❌ NG: ハードコード
Icon(LucideIcons.star, color: Colors.blue)
Icon(LucideIcons.star, color: Color(0xFF376495))
Container(color: Colors.white)
```
### 2. 手動Dark Mode条件分岐
```dart
// ❌ 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の直接使用
```dart
// ❌ NG: primaryColorは内部でDark/Light切り替えが必要
Icon(LucideIcons.star, color: Theme.of(context).primaryColor)
```
---
## ✅ 正しい使い方
### Material 3 ColorSchemeを使う
Flutter Material 3は、Dark/Light両モードに自動対応する**セマンティックカラー**を提供しています。
#### 基本パターン
```dart
// ✅ 正しい: 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)` | 自動調整 | 自動調整 | チップ、バッジ背景 |
---
## 🔧 実装例
### ✅ アイコン
```dart
// セクションヘッダー(アクセントカラー)
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)
```
### ✅ テキスト
```dart
// 見出し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,
),
)
```
### ✅ 背景色
```dart
// カード背景
Container(
color: Theme.of(context).colorScheme.surface,
child: ...,
)
// 半透明背景(ブランドカラー)
Container(
color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.1),
child: ...,
)
```
### ✅ ボタン
```dart
// プライマリボタン
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('アクション'),
)
```
---
## 🚨 特殊ケース(例外)
### エラー・警告・成功(セマンティックカラー)
一部の色は**意味が固定**されているため、ハードコードが許可されます:
```dart
// ✅ OK: エラーは常に赤
Icon(LucideIcons.alertTriangle, color: Colors.red)
// ✅ OK: 成功は常に緑
Icon(LucideIcons.checkCircle, color: Colors.green)
// ✅ OK: 警告は常にオレンジ
Icon(LucideIcons.info, color: Colors.orange)
```
ただし、可能な限り `colorScheme.error` を使用してください:
```dart
// ✅ より良い: Material 3のエラーカラー
Icon(LucideIcons.alertTriangle, color: Theme.of(context).colorScheme.error)
```
---
## 🔍 既存コードの修正方法
### パターン1: primaryColor → colorScheme.primary
```dart
// Before ❌
Icon(LucideIcons.star, color: Theme.of(context).primaryColor)
// After ✅
Icon(LucideIcons.star, color: Theme.of(context).colorScheme.primary)
```
### パターン2: 手動条件分岐 → colorScheme.onSurface
```dart
// 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
```dart
// 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` を使用
---
## 🔗 参考資料
- [Material 3 Color System](https://m3.material.io/styles/color/the-color-system/overview)
- [Flutter ColorScheme API](https://api.flutter.dev/flutter/material/ColorScheme-class.html)
---
**最終更新:** 2026-01-21
**作成者:** Claude (Antigravity AI)