ponshu-room-lite/lib/theme/app_theme.dart

178 lines
6.5 KiB
Dart
Raw Permalink 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.

import 'package:flutter/material.dart';
import 'package:google_fonts/google_fonts.dart';
import 'app_colors.dart'; // Import Extension
enum AppFontStyle {
sans, // Noto Sans JP (ゴシック)
serif, // Noto Serif JP (明朝)
pottaOne, // Potta One (髭文字)
digital, // DotGothic16 (ドット)
}
enum ColorVariant {
washiSumiKohaku, // 和紙×墨×琥珀 (Theme A)
current, // Current theme (Theme B)
}
class AppTheme {
static const Color posimaiBlue = Color(0xFF376495);
// ===== Theme A: 和紙×墨×琥珀 (Washi × Sumi × Kohaku) =====
// 日本酒の世界観を反映した洗練された配色
static const Color washiWhite = Color(0xFFFDFBF7); // 和紙の温かみのある白
static const Color sumiBlack = Color(0xFF4A3B32); // 墨色(温かみのある焦げ茶)
static const Color kohakuGold = Color(0xFFD4A574); // 琥珀色(酒の黄金色)
static const Color kohakuDeep = Color(0xFFB8860B); // 深い琥珀(アクセント用)
// ===== Theme B: Current (Original) =====
// 既存のPosimai Blueベースのテーマ
// Padding Constants
static const double spacingEmpty = 0.0;
static const double spacingTiny = 4.0;
static const double spacingSmall = 8.0;
static const double spacingMedium = 16.0;
static const double spacingLarge = 24.0;
static const double spacingXLarge = 32.0;
static ThemeData createTheme(
AppFontStyle fontStyle,
Brightness brightness,
ColorVariant colorVariant,
) {
/*
Why GoogleFonts is safe:
1. Downloads dynamically (no asset size increase).
2. Caches locally (fast 2nd load).
3. Fallback exists during download.
*/
final TextTheme textTheme;
switch (fontStyle) {
case AppFontStyle.sans:
textTheme = GoogleFonts.notoSansJpTextTheme();
case AppFontStyle.serif:
textTheme = GoogleFonts.notoSerifJpTextTheme();
case AppFontStyle.pottaOne:
textTheme = GoogleFonts.pottaOneTextTheme();
case AppFontStyle.digital:
textTheme = GoogleFonts.dotGothic16TextTheme();
}
// Get AppColors for this theme variant
final appColors = _getAppColors(colorVariant, brightness);
// Color scheme based on variant
final ColorScheme colorScheme;
if (colorVariant == ColorVariant.washiSumiKohaku) {
// Theme A: 和紙×墨×琥珀
colorScheme = ColorScheme.fromSeed(
seedColor: kohakuGold,
brightness: brightness,
).copyWith(
primary: brightness == Brightness.dark
? kohakuGold // 琥珀色 for dark mode
: sumiBlack, // 墨色 for light mode
surface: brightness == Brightness.dark
? const Color(0xFF1E1E1E)
: washiWhite, // 和紙ホワイト
secondary: brightness == Brightness.dark
? kohakuDeep // 深い琥珀 for dark mode
: kohakuGold, // 琥珀色 for light mode
);
} else {
// Theme B: Current (Original)
colorScheme = ColorScheme.fromSeed(
seedColor: posimaiBlue,
brightness: brightness,
).copyWith(
primary: brightness == Brightness.dark
? const Color(0xFF8AB4F8) // Bright blue for dark mode
: posimaiBlue, // Original blue for light mode
surface: brightness == Brightness.dark
? const Color(0xFF1E1E1E)
: Colors.white,
secondary: brightness == Brightness.dark
? const Color(0xFFFFB74D) // Warm orange for dark mode accents
: const Color(0xFFFF6F00), // Deep orange for light mode
);
}
return ThemeData(
useMaterial3: true,
colorScheme: colorScheme,
textTheme: textTheme.apply(
bodyColor: (brightness == Brightness.dark) ? Colors.white : Colors.black87,
displayColor: (brightness == Brightness.dark) ? Colors.white : Colors.black87,
).copyWith(
// Ensure headers/labels are visible
titleMedium: TextStyle(color: (brightness == Brightness.dark) ? Colors.white : Colors.black87),
titleSmall: TextStyle(color: (brightness == Brightness.dark) ? Colors.white70 : Colors.black54),
labelLarge: TextStyle(color: (brightness == Brightness.dark) ? Colors.white : Colors.black87),
),
scaffoldBackgroundColor: (brightness == Brightness.dark)
? const Color(0xFF121212)
: (colorVariant == ColorVariant.washiSumiKohaku
? washiWhite
: const Color(0xFFFAFAFA)),
cardTheme: CardThemeData(
elevation: 0,
margin: EdgeInsets.zero,
color: (brightness == Brightness.dark)
? const Color(0xFF1E1E1E)
: (colorVariant == ColorVariant.washiSumiKohaku
? Colors.white
: Colors.white),
),
appBarTheme: AppBarTheme(
// UI/UX Consistency: AppBarとNavigationBarの背景色を統一ダークモードのみ
backgroundColor: (brightness == Brightness.dark) ? const Color(0xFF1E1E1E) : null,
foregroundColor: (brightness == Brightness.dark) ? Colors.white : Colors.black87,
actionsIconTheme: IconThemeData(
color: (brightness == Brightness.dark) ? Colors.white : Colors.black87,
),
iconTheme: IconThemeData(
color: (brightness == Brightness.dark) ? Colors.white : Colors.black87,
),
),
iconTheme: IconThemeData(
color: (brightness == Brightness.dark)
? Colors.white
: (colorVariant == ColorVariant.washiSumiKohaku
? sumiBlack
: posimaiBlue),
),
navigationBarTheme: NavigationBarThemeData(
backgroundColor: (brightness == Brightness.dark) ? const Color(0xFF1E1E1E) : null,
indicatorColor: brightness == Brightness.dark
? appColors.brandPrimary.withValues(alpha: 0.4)
: appColors.brandPrimary.withValues(alpha: 0.25),
),
extensions: [
_getAppColors(colorVariant, brightness),
],
);
}
/// AppColorsインスタンスを取得テーマバリアントとブライトネスに基づく
static AppColors _getAppColors(ColorVariant colorVariant, Brightness brightness) {
if (colorVariant == ColorVariant.washiSumiKohaku) {
return brightness == Brightness.dark
? AppColors.washiDark()
: AppColors.washiLight();
} else {
return brightness == Brightness.dark
? AppColors.currentDark()
: AppColors.currentLight();
}
}
}