295 lines
11 KiB
Dart
295 lines
11 KiB
Dart
import 'package:flutter/material.dart';
|
||
|
||
/// AppColors ThemeExtension
|
||
///
|
||
/// セマンティックカラーシステム:色の「意味」に基づいて定義
|
||
/// テーマバリアント(和紙×墨×琥珀 / Current)とブライトネス(Light/Dark)に完全対応
|
||
///
|
||
/// 使用例:
|
||
/// ```dart
|
||
/// final colors = Theme.of(context).extension<AppColors>()!;
|
||
/// Icon(icon, color: colors.brandPrimary);
|
||
/// Text('テキスト', style: TextStyle(color: colors.textPrimary));
|
||
/// ```
|
||
@immutable
|
||
class AppColors extends ThemeExtension<AppColors> {
|
||
// ===== テキストカラー(構造的) =====
|
||
/// メインテキスト(本文、タイトル)
|
||
final Color textPrimary;
|
||
/// セカンダリテキスト(説明文、補足)
|
||
final Color textSecondary;
|
||
/// ターシャリテキスト(無効化、プレースホルダー)
|
||
final Color textTertiary;
|
||
|
||
// ===== ブランドカラー(テーマバリアント依存) =====
|
||
/// プライマリブランドカラー
|
||
/// - Washi Light: 墨色(焦げ茶)
|
||
/// - Washi Dark: 琥珀色(ゴールド)
|
||
/// - Current Light: Posimai Blue
|
||
/// - Current Dark: ライトブルー
|
||
final Color brandPrimary;
|
||
|
||
/// アクセントブランドカラー
|
||
/// - Washi Light: 琥珀色
|
||
/// - Washi Dark: 深い琥珀
|
||
/// - Current Light: オレンジ
|
||
/// - Current Dark: ライトオレンジ
|
||
final Color brandAccent;
|
||
|
||
/// サーフェイスブランドカラー(背景のティント)
|
||
/// - Washi Light: 和紙ホワイト
|
||
/// - Washi Dark: ダークグレー
|
||
/// - Current Light: ホワイト
|
||
/// - Current Dark: ダークグレー
|
||
final Color brandSurface;
|
||
|
||
// ===== アイコンカラー =====
|
||
/// デフォルトアイコンカラー(通常のアイコン)
|
||
final Color iconDefault;
|
||
/// サブアイコンカラー(セカンダリ、無効化)
|
||
final Color iconSubtle;
|
||
/// アクセントアイコンカラー(強調、アクション)
|
||
final Color iconAccent;
|
||
|
||
// ===== サーフェイスカラー =====
|
||
/// カード背景、エレベーション
|
||
final Color surfaceElevated;
|
||
/// サブトル背景(微妙な差)
|
||
final Color surfaceSubtle;
|
||
/// ボーダー、区切り線
|
||
final Color divider;
|
||
|
||
// ===== セマンティックカラー(機能的) =====
|
||
/// 成功、安全(緑系)
|
||
final Color success;
|
||
/// 警告、注意(オレンジ系)
|
||
final Color warning;
|
||
/// エラー、危険(赤系)
|
||
final Color error;
|
||
/// 情報、中立(青系)
|
||
final Color info;
|
||
|
||
const AppColors({
|
||
required this.textPrimary,
|
||
required this.textSecondary,
|
||
required this.textTertiary,
|
||
required this.brandPrimary,
|
||
required this.brandAccent,
|
||
required this.brandSurface,
|
||
required this.iconDefault,
|
||
required this.iconSubtle,
|
||
required this.iconAccent,
|
||
required this.surfaceElevated,
|
||
required this.surfaceSubtle,
|
||
required this.divider,
|
||
required this.success,
|
||
required this.warning,
|
||
required this.error,
|
||
required this.info,
|
||
});
|
||
|
||
@override
|
||
AppColors copyWith({
|
||
Color? textPrimary,
|
||
Color? textSecondary,
|
||
Color? textTertiary,
|
||
Color? brandPrimary,
|
||
Color? brandAccent,
|
||
Color? brandSurface,
|
||
Color? iconDefault,
|
||
Color? iconSubtle,
|
||
Color? iconAccent,
|
||
Color? surfaceElevated,
|
||
Color? surfaceSubtle,
|
||
Color? divider,
|
||
Color? success,
|
||
Color? warning,
|
||
Color? error,
|
||
Color? info,
|
||
}) {
|
||
return AppColors(
|
||
textPrimary: textPrimary ?? this.textPrimary,
|
||
textSecondary: textSecondary ?? this.textSecondary,
|
||
textTertiary: textTertiary ?? this.textTertiary,
|
||
brandPrimary: brandPrimary ?? this.brandPrimary,
|
||
brandAccent: brandAccent ?? this.brandAccent,
|
||
brandSurface: brandSurface ?? this.brandSurface,
|
||
iconDefault: iconDefault ?? this.iconDefault,
|
||
iconSubtle: iconSubtle ?? this.iconSubtle,
|
||
iconAccent: iconAccent ?? this.iconAccent,
|
||
surfaceElevated: surfaceElevated ?? this.surfaceElevated,
|
||
surfaceSubtle: surfaceSubtle ?? this.surfaceSubtle,
|
||
divider: divider ?? this.divider,
|
||
success: success ?? this.success,
|
||
warning: warning ?? this.warning,
|
||
error: error ?? this.error,
|
||
info: info ?? this.info,
|
||
);
|
||
}
|
||
|
||
@override
|
||
AppColors lerp(ThemeExtension<AppColors>? other, double t) {
|
||
if (other is! AppColors) {
|
||
return this;
|
||
}
|
||
return AppColors(
|
||
textPrimary: Color.lerp(textPrimary, other.textPrimary, t)!,
|
||
textSecondary: Color.lerp(textSecondary, other.textSecondary, t)!,
|
||
textTertiary: Color.lerp(textTertiary, other.textTertiary, t)!,
|
||
brandPrimary: Color.lerp(brandPrimary, other.brandPrimary, t)!,
|
||
brandAccent: Color.lerp(brandAccent, other.brandAccent, t)!,
|
||
brandSurface: Color.lerp(brandSurface, other.brandSurface, t)!,
|
||
iconDefault: Color.lerp(iconDefault, other.iconDefault, t)!,
|
||
iconSubtle: Color.lerp(iconSubtle, other.iconSubtle, t)!,
|
||
iconAccent: Color.lerp(iconAccent, other.iconAccent, t)!,
|
||
surfaceElevated: Color.lerp(surfaceElevated, other.surfaceElevated, t)!,
|
||
surfaceSubtle: Color.lerp(surfaceSubtle, other.surfaceSubtle, t)!,
|
||
divider: Color.lerp(divider, other.divider, t)!,
|
||
success: Color.lerp(success, other.success, t)!,
|
||
warning: Color.lerp(warning, other.warning, t)!,
|
||
error: Color.lerp(error, other.error, t)!,
|
||
info: Color.lerp(info, other.info, t)!,
|
||
);
|
||
}
|
||
|
||
// ===== ファクトリーメソッド:和紙×墨×琥珀テーマ =====
|
||
|
||
/// 和紙×墨×琥珀 ライトモード
|
||
/// - プライマリ: 墨色(焦げ茶)
|
||
/// - アクセント: 琥珀色(ゴールド)
|
||
/// - サーフェイス: 和紙ホワイト
|
||
static AppColors washiLight() {
|
||
return const AppColors(
|
||
// テキスト
|
||
textPrimary: Color(0xFF2C2C2C), // ほぼ黒(墨インスパイア)
|
||
textSecondary: Color(0xFF757575), // グレー
|
||
textTertiary: Color(0xFFBDBDBD), // ライトグレー
|
||
|
||
// ブランド
|
||
brandPrimary: Color(0xFF4A3B32), // 墨色(焦げ茶)
|
||
brandAccent: Color(0xFFD4A574), // 琥珀色
|
||
brandSurface: Color(0xFFFDFBF7), // 和紙ホワイト
|
||
|
||
// アイコン
|
||
iconDefault: Color(0xFF4A3B32), // 墨色
|
||
iconSubtle: Color(0xFF9E9E9E), // グレー
|
||
iconAccent: Color(0xFFD4A574), // 琥珀色
|
||
|
||
// サーフェイス
|
||
surfaceElevated: Color(0xFFFFFFFF), // 純白(カード)
|
||
surfaceSubtle: Color(0xFFF5F5F5), // オフホワイト
|
||
divider: Color(0xFFE0E0E0), // ライトグレー
|
||
|
||
// セマンティック
|
||
success: Color(0xFF388E3C), // 緑
|
||
warning: Color(0xFFF57C00), // オレンジ
|
||
error: Color(0xFFD32F2F), // 赤
|
||
info: Color(0xFF1976D2), // 青
|
||
);
|
||
}
|
||
|
||
/// 和紙×墨×琥珀 ダークモード
|
||
/// - プライマリ: 琥珀色(ゴールド)
|
||
/// - アクセント: 深い琥珀
|
||
/// - サーフェイス: ダークグレー
|
||
static AppColors washiDark() {
|
||
return const AppColors(
|
||
// テキスト
|
||
textPrimary: Color(0xFFFFFFFF), // 白
|
||
textSecondary: Color(0xFFBDBDBD), // ライトグレー
|
||
textTertiary: Color(0xFF757575), // グレー
|
||
|
||
// ブランド
|
||
brandPrimary: Color(0xFFD4A574), // 琥珀色(ゴールド)
|
||
brandAccent: Color(0xFFB8860B), // 深い琥珀
|
||
brandSurface: Color(0xFF1E1E1E), // ダークグレー
|
||
|
||
// アイコン
|
||
iconDefault: Color(0xFFD4A574), // 琥珀色
|
||
iconSubtle: Color(0xFF9E9E9E), // グレー
|
||
iconAccent: Color(0xFFFFD54F), // ライトゴールド
|
||
|
||
// サーフェイス
|
||
surfaceElevated: Color(0xFF2C2C2C), // ややライトなダーク
|
||
surfaceSubtle: Color(0xFF1A1A1A), // 深いダーク
|
||
divider: Color(0xFF424242), // ダークグレー
|
||
|
||
// セマンティック
|
||
success: Color(0xFF66BB6A), // ライトグリーン
|
||
warning: Color(0xFFFFB74D), // ライトオレンジ
|
||
error: Color(0xFFEF5350), // ライトレッド
|
||
info: Color(0xFF42A5F5), // ライトブルー
|
||
);
|
||
}
|
||
|
||
// ===== ファクトリーメソッド:Currentテーマ(オリジナル) =====
|
||
|
||
/// Current(オリジナル)ライトモード
|
||
/// - プライマリ: Posimai Blue
|
||
/// - アクセント: オレンジ
|
||
/// - サーフェイス: ホワイト
|
||
static AppColors currentLight() {
|
||
return const AppColors(
|
||
// テキスト
|
||
textPrimary: Color(0xFF212121), // ほぼ黒
|
||
textSecondary: Color(0xFF757575), // グレー
|
||
textTertiary: Color(0xFFBDBDBD), // ライトグレー
|
||
|
||
// ブランド
|
||
brandPrimary: Color(0xFF376495), // Posimai Blue
|
||
brandAccent: Color(0xFFFF6F00), // 深いオレンジ
|
||
brandSurface: Color(0xFFFFFFFF), // 純白
|
||
|
||
// アイコン
|
||
iconDefault: Color(0xFF376495), // Posimai Blue
|
||
iconSubtle: Color(0xFF9E9E9E), // グレー
|
||
iconAccent: Color(0xFFFF6F00), // オレンジ
|
||
|
||
// サーフェイス
|
||
surfaceElevated: Color(0xFFFFFFFF), // 純白
|
||
surfaceSubtle: Color(0xFFFAFAFA), // オフホワイト
|
||
divider: Color(0xFFE0E0E0), // ライトグレー
|
||
|
||
// セマンティック
|
||
success: Color(0xFF388E3C), // 緑
|
||
warning: Color(0xFFF57C00), // オレンジ
|
||
error: Color(0xFFD32F2F), // 赤
|
||
info: Color(0xFF1976D2), // 青
|
||
);
|
||
}
|
||
|
||
/// Current(オリジナル)ダークモード
|
||
/// - プライマリ: ライトブルー
|
||
/// - アクセント: ライトオレンジ
|
||
/// - サーフェイス: ダークグレー
|
||
static AppColors currentDark() {
|
||
return const AppColors(
|
||
// テキスト
|
||
textPrimary: Color(0xFFFFFFFF), // 白
|
||
textSecondary: Color(0xFFBDBDBD), // ライトグレー
|
||
textTertiary: Color(0xFF757575), // グレー
|
||
|
||
// ブランド
|
||
brandPrimary: Color(0xFF8AB4F8), // ライトブルー
|
||
brandAccent: Color(0xFFFFB74D), // ライトオレンジ
|
||
brandSurface: Color(0xFF1E1E1E), // ダークグレー
|
||
|
||
// アイコン
|
||
iconDefault: Color(0xFF8AB4F8), // ライトブルー
|
||
iconSubtle: Color(0xFF9E9E9E), // グレー
|
||
iconAccent: Color(0xFFFFB74D), // ライトオレンジ
|
||
|
||
// サーフェイス
|
||
surfaceElevated: Color(0xFF2C2C2C), // ややライトなダーク
|
||
surfaceSubtle: Color(0xFF1A1A1A), // 深いダーク
|
||
divider: Color(0xFF424242), // ダークグレー
|
||
|
||
// セマンティック
|
||
success: Color(0xFF66BB6A), // ライトグリーン
|
||
warning: Color(0xFFFFB74D), // ライトオレンジ
|
||
error: Color(0xFFEF5350), // ライトレッド
|
||
info: Color(0xFF42A5F5), // ライトブルー
|
||
);
|
||
}
|
||
}
|