BioFlow Requirements
lib\presentation\theme\app_theme.dart
Source file coverage
Path:
lib/presentation/theme/app_theme.dart
Lines:
273
Non-empty lines:
250
Non-empty lines covered with requirements:
250 / 250 (100.0%)
Functions:
0
Functions covered by requirements:
0 / 0 (0.0%)
1
import 'package:bioflow_pro/domain/value_objects/ui/theme_type.dart';
2
import 'package:bioflow_pro/presentation/theme/bioflow_theme_extension.dart';
3
import 'package:bioflow_pro/presentation/theme/design_system.dart';
4
import 'package:flutter/material.dart';
5
 
6
// @relation(ARCH-011, scope=file)
7
/// Application theme configuration with BioFlow design system
8
///
9
/// Integrates Material Design 3 with BioFlow's medical purple palette
10
/// and custom glassmorphism theme extension.
11
class AppTheme {
12
  /// Create ThemeData for a specific preset theme type
13
  static ThemeData forPreset(ThemeType themeType) {
14
    switch (themeType) {
15
      case ThemeType.minimal:
16
        return _minimalTheme;
17
      case ThemeType.darkGlass:
18
        return _darkGlassTheme;
19
      case ThemeType.minimalLight:
20
        return _minimalLightTheme;
21
    }
22
  }
23
 
24
  /// Dark Glass theme - Main glassmorphism theme
25
  static ThemeData get _darkGlassTheme {
26
    return _baseTheme(
27
      brightness: Brightness.light,
28
      extension: BioFlowThemeExtension.darkGlass(),
29
    );
30
  }
31
 
32
  /// Minimal theme - Opaque backgrounds, no blur
33
  static ThemeData get _minimalTheme {
34
    return _baseTheme(
35
      brightness: Brightness.dark,
36
      extension: BioFlowThemeExtension.minimal(),
37
    );
38
  }
39
 
40
  /// Minimal Light theme - Light opaque backgrounds, no blur
41
  static ThemeData get _minimalLightTheme {
42
    return _baseLightTheme(
43
      extension: BioFlowThemeExtension.minimalLight(),
44
    );
45
  }
46
 
47
  /// Base theme configuration with BioFlow colors
48
  static ThemeData _baseTheme({
49
    required Brightness brightness,
50
    required BioFlowThemeExtension extension,
51
  }) {
52
    // Use BioFlow medical purple palette
53
    const primaryColor = BioFlowColors.electricViolet;
54
    const secondaryColor = BioFlowColors.glassPurple;
55
    final backgroundColor = brightness == Brightness.dark
56
        ? BioFlowColors.primaryDark
57
        : BioFlowColors.backgroundPrimary;
58
    final surfaceColor = brightness == Brightness.dark
59
        ? BioFlowColors.primaryDark
60
        : BioFlowColors.backgroundSecondary;
61
 
62
    return ThemeData(
63
      useMaterial3: true,
64
      brightness: brightness,
65
      colorScheme: ColorScheme.fromSeed(
66
        seedColor: primaryColor,
67
        brightness: brightness,
68
        primary: primaryColor,
69
        secondary: secondaryColor,
70
        surface: surfaceColor,
71
        error: BioFlowColors.medicalRed,
72
      ),
73
      scaffoldBackgroundColor: backgroundColor,
74
      extensions: [extension],
75
 
76
      // AppBar theme with glassmorphism effect
77
      appBarTheme: AppBarTheme(
78
        centerTitle: false,
79
        elevation: 0,
80
        backgroundColor: Colors.transparent,
81
        foregroundColor: primaryColor,
82
        titleTextStyle: TextStyle(
83
          color: BioFlowColors.textPrimary,
84
          fontSize: 20,
85
          fontWeight: FontWeight.w600,
86
        ),
87
      ),
88
 
89
      // Card theme with glassmorphism
90
      cardTheme: CardThemeData(
91
        elevation: 0,
92
        color: surfaceColor.withValues(alpha: 0.8),
93
        shape: RoundedRectangleBorder(
94
          borderRadius: BorderRadius.circular(BioFlowRadius.lg),
95
        ),
96
      ),
97
 
98
      // Elevated button theme
99
      elevatedButtonTheme: ElevatedButtonThemeData(
100
        style: ElevatedButton.styleFrom(
101
          elevation: 0,
102
          padding: const EdgeInsets.symmetric(
103
            horizontal: BioFlowSpacing.lg,
104
            vertical: BioFlowSpacing.md,
105
          ),
106
          shape: RoundedRectangleBorder(
107
            borderRadius: BorderRadius.circular(BioFlowRadius.md),
108
          ),
109
        ),
110
      ),
111
 
112
      // Input decoration theme
113
      inputDecorationTheme: InputDecorationTheme(
114
        filled: true,
115
        fillColor: surfaceColor.withValues(alpha: 0.5),
116
        border: OutlineInputBorder(
117
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
118
          borderSide: BorderSide.none,
119
        ),
120
        enabledBorder: OutlineInputBorder(
121
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
122
          borderSide: BorderSide(
123
            color: primaryColor.withValues(alpha: 0.2),
124
            width: 1,
125
          ),
126
        ),
127
        focusedBorder: OutlineInputBorder(
128
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
129
          borderSide: const BorderSide(
130
            color: primaryColor,
131
            width: 2,
132
          ),
133
        ),
134
      ),
135
 
136
      // SnackBar theme with centered behavior
137
      snackBarTheme: SnackBarThemeData(
138
        behavior: SnackBarBehavior.floating,
139
        backgroundColor: surfaceColor,
140
        contentTextStyle: const TextStyle(
141
          fontSize: 14,
142
          fontWeight: FontWeight.w500,
143
        ),
144
      ),
145
    );
146
  }
147
 
148
  /// Base light theme configuration for Minimal Light theme
149
  static ThemeData _baseLightTheme({
150
    required BioFlowThemeExtension extension,
151
  }) {
152
    const primaryColor = BioFlowColors.electricViolet;
153
    const secondaryColor = BioFlowColors.glassPurple;
154
    const backgroundColor = BioFlowColors.backgroundLightPrimary;
155
    const surfaceColor = BioFlowColors.backgroundLightSecondary;
156
 
157
    return ThemeData(
158
      useMaterial3: true,
159
      brightness: Brightness.light,
160
      colorScheme: ColorScheme.fromSeed(
161
        seedColor: primaryColor,
162
        brightness: Brightness.light,
163
        primary: primaryColor,
164
        secondary: secondaryColor,
165
        surface: surfaceColor,
166
        error: BioFlowColors.medicalRed,
167
      ),
168
      scaffoldBackgroundColor: backgroundColor,
169
      extensions: [extension],
170
 
171
      // AppBar theme
172
      appBarTheme: const AppBarTheme(
173
        centerTitle: false,
174
        elevation: 0,
175
        backgroundColor: Colors.transparent,
176
        foregroundColor: primaryColor,
177
        titleTextStyle: TextStyle(
178
          color: BioFlowColors.textLightPrimary,
179
          fontSize: 20,
180
          fontWeight: FontWeight.w600,
181
        ),
182
      ),
183
 
184
      // Card theme
185
      cardTheme: CardThemeData(
186
        elevation: 0,
187
        color: surfaceColor,
188
        shape: RoundedRectangleBorder(
189
          borderRadius: BorderRadius.circular(BioFlowRadius.lg),
190
        ),
191
      ),
192
 
193
      // Elevated button theme
194
      elevatedButtonTheme: ElevatedButtonThemeData(
195
        style: ElevatedButton.styleFrom(
196
          elevation: 0,
197
          padding: const EdgeInsets.symmetric(
198
            horizontal: BioFlowSpacing.lg,
199
            vertical: BioFlowSpacing.md,
200
          ),
201
          shape: RoundedRectangleBorder(
202
            borderRadius: BorderRadius.circular(BioFlowRadius.md),
203
          ),
204
        ),
205
      ),
206
 
207
      // Input decoration theme
208
      inputDecorationTheme: InputDecorationTheme(
209
        filled: true,
210
        fillColor: surfaceColor,
211
        border: OutlineInputBorder(
212
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
213
          borderSide: BorderSide.none,
214
        ),
215
        enabledBorder: OutlineInputBorder(
216
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
217
          borderSide: BorderSide(
218
            color: BioFlowColors.borderLightSecondary,
219
            width: 1,
220
          ),
221
        ),
222
        focusedBorder: OutlineInputBorder(
223
          borderRadius: BorderRadius.circular(BioFlowRadius.md),
224
          borderSide: const BorderSide(
225
            color: primaryColor,
226
            width: 2,
227
          ),
228
        ),
229
      ),
230
 
231
      // SnackBar theme with centered behavior
232
      snackBarTheme: const SnackBarThemeData(
233
        behavior: SnackBarBehavior.floating,
234
        contentTextStyle: TextStyle(
235
          fontSize: 14,
236
          fontWeight: FontWeight.w500,
237
        ),
238
      ),
239
 
240
      // Text theme with dark text colors for light background
241
      textTheme: const TextTheme(
242
        bodyLarge: TextStyle(color: BioFlowColors.textLightPrimary),
243
        bodyMedium: TextStyle(color: BioFlowColors.textLightSecondary),
244
        bodySmall: TextStyle(color: BioFlowColors.textLightTertiary),
245
        titleLarge: TextStyle(color: BioFlowColors.textLightPrimary),
246
        titleMedium: TextStyle(color: BioFlowColors.textLightPrimary),
247
        titleSmall: TextStyle(color: BioFlowColors.textLightPrimary),
248
        labelLarge: TextStyle(color: BioFlowColors.textLightPrimary),
249
        labelMedium: TextStyle(color: BioFlowColors.textLightSecondary),
250
        labelSmall: TextStyle(color: BioFlowColors.textLightTertiary),
251
      ),
252
 
253
      // Icon theme
254
      iconTheme: const IconThemeData(
255
        color: BioFlowColors.textLightPrimary,
256
      ),
257
    );
258
  }
259
 
260
  // ==================== Backward Compatibility ====================
261
 
262
  /// Light theme - Defaults to Dark Glass theme
263
  ///
264
  /// For backward compatibility. New code should use forPreset() instead.
265
  @Deprecated('Use AppTheme.forPreset(ThemeType) instead')
266
  static ThemeData get lightTheme => _darkGlassTheme;
267
 
268
  /// Dark theme - Defaults to Minimal theme
269
  ///
270
  /// For backward compatibility. New code should use forPreset() instead.
271
  @Deprecated('Use AppTheme.forPreset(ThemeType) instead')
272
  static ThemeData get darkTheme => _minimalTheme;
273
}