updates themeing to align better with website harmonies
This commit is contained in:
+27
-19
@@ -111,38 +111,46 @@ class AppConfig {{
|
||||
def generate_theme_colors(theme: dict) -> str:
|
||||
c = theme["colors"]
|
||||
|
||||
# Light mode
|
||||
# Light mode — mapped to match companion website color usage
|
||||
light_props = [
|
||||
("primarySeed", hex_to_rgba(c["primary"])),
|
||||
("secondarySeed", hex_to_rgba(c["accent"])),
|
||||
("headingColor", hex_to_rgba(c["primary"])),
|
||||
("accentColor", hex_to_rgba(c["accent"])),
|
||||
("scaffoldGradientStart", hex_to_rgba(c["background"])),
|
||||
("scaffoldGradientEnd", hex_to_rgba(c["light"])),
|
||||
("shellSurface", hex_to_rgba(c["white"], 0.97)),
|
||||
("shellBorder", hex_to_rgba(c["medium"], 0.10)),
|
||||
("accent", hex_to_rgba(c["accent_dark"])),
|
||||
("webViewBorder", hex_to_rgba(c["medium"], 0.15)),
|
||||
("webViewBackground", hex_to_rgba(c["white"])),
|
||||
("controlsGradientStart", hex_to_rgba(c["primary_muted"])),
|
||||
("controlsGradientEnd", hex_to_rgba(c["accent_muted"])),
|
||||
("mutedText", hex_to_rgba(c["medium"])),
|
||||
("textOnDark", hex_to_rgba(c["white"])),
|
||||
("textOnDarkSecondary", hex_to_rgba(c["light"])),
|
||||
("controlsGradientStart", hex_to_rgba(c["primary"])),
|
||||
("controlsGradientEnd", hex_to_rgba(c["primary_light"])),
|
||||
("controlsShadow", hex_to_rgba(c["black"], 0.14)),
|
||||
("statusText", hex_to_rgba(c["text"])),
|
||||
("bodyText", hex_to_rgba(c["text"])),
|
||||
("cardSurface", hex_to_rgba(c["white"], 0.08)),
|
||||
("cardBorder", hex_to_rgba(c["white"], 0.12)),
|
||||
("successColor", hex_to_rgba(c["success"])),
|
||||
("dangerColor", hex_to_rgba(c["danger"])),
|
||||
]
|
||||
|
||||
# Dark mode
|
||||
# Dark mode — mapped to match companion website color usage
|
||||
dark_props = [
|
||||
("primarySeed", hex_to_rgba(c["primary_light"])),
|
||||
("secondarySeed", hex_to_rgba(c["accent_light"])),
|
||||
("headingColor", hex_to_rgba(c["primary_light"])),
|
||||
("accentColor", hex_to_rgba(c["accent_light"])),
|
||||
("scaffoldGradientStart", hex_to_rgba(c["black"])),
|
||||
("scaffoldGradientEnd", darken(c["primary_dark"], 0.30)),
|
||||
("shellSurface", hex_to_rgba(c["black"], 0.85)),
|
||||
("shellBorder", hex_to_rgba(c["accent_light"], 0.20)),
|
||||
("accent", hex_to_rgba(c["primary_light"])),
|
||||
("webViewBorder", hex_to_rgba(c["accent_light"], 0.20)),
|
||||
("webViewBackground", hex_to_rgba(c["black"])),
|
||||
("shellSurface", hex_to_rgba(c["primary_dark"], 0.85)),
|
||||
("shellBorder", hex_to_rgba(c["medium"], 0.20)),
|
||||
("mutedText", hex_to_rgba(c["medium"])),
|
||||
("textOnDark", hex_to_rgba(c["white"])),
|
||||
("textOnDarkSecondary", hex_to_rgba(c["light"])),
|
||||
("controlsGradientStart", hex_to_rgba(c["primary_dark"])),
|
||||
("controlsGradientEnd", hex_to_rgba(c["accent_dark"])),
|
||||
("controlsGradientEnd", hex_to_rgba(c["primary"])),
|
||||
("controlsShadow", hex_to_rgba(c["black"], 0.27)),
|
||||
("statusText", hex_to_rgba(c["light"])),
|
||||
("bodyText", hex_to_rgba(c["light"])),
|
||||
("cardSurface", hex_to_rgba(c["white"], 0.08)),
|
||||
("cardBorder", hex_to_rgba(c["white"], 0.12)),
|
||||
("successColor", hex_to_rgba(c["success"])),
|
||||
("dangerColor", hex_to_rgba(c["danger"])),
|
||||
]
|
||||
|
||||
def props_block(props, indent: str = " ") -> str:
|
||||
|
||||
@@ -4,34 +4,59 @@ import 'generated/theme_colors.dart';
|
||||
|
||||
class AppThemeColors {
|
||||
const AppThemeColors({
|
||||
required this.primarySeed,
|
||||
required this.secondarySeed,
|
||||
required this.headingColor,
|
||||
required this.accentColor,
|
||||
required this.scaffoldGradientStart,
|
||||
required this.scaffoldGradientEnd,
|
||||
required this.shellSurface,
|
||||
required this.shellBorder,
|
||||
required this.accent,
|
||||
required this.webViewBorder,
|
||||
required this.webViewBackground,
|
||||
required this.mutedText,
|
||||
required this.textOnDark,
|
||||
required this.textOnDarkSecondary,
|
||||
required this.controlsGradientStart,
|
||||
required this.controlsGradientEnd,
|
||||
required this.controlsShadow,
|
||||
required this.statusText,
|
||||
required this.bodyText,
|
||||
required this.cardSurface,
|
||||
required this.cardBorder,
|
||||
required this.successColor,
|
||||
required this.dangerColor,
|
||||
});
|
||||
|
||||
final Color primarySeed;
|
||||
final Color secondarySeed;
|
||||
/// Website: `primary` → headings (h1–h6)
|
||||
final Color headingColor;
|
||||
/// Website: `accent` → links & accent highlights
|
||||
final Color accentColor;
|
||||
/// Page background gradient start — website: `background` (cream)
|
||||
final Color scaffoldGradientStart;
|
||||
/// Page background gradient end — website: `light`
|
||||
final Color scaffoldGradientEnd;
|
||||
/// Top header card surface
|
||||
final Color shellSurface;
|
||||
/// Top header card border
|
||||
final Color shellBorder;
|
||||
final Color accent;
|
||||
final Color webViewBorder;
|
||||
final Color webViewBackground;
|
||||
/// Website: `medium` → muted / secondary text
|
||||
final Color mutedText;
|
||||
/// Website: `white` → text on dark surfaces
|
||||
final Color textOnDark;
|
||||
/// Website: `light` → secondary text on dark surfaces
|
||||
final Color textOnDarkSecondary;
|
||||
/// Controls bar / card surface gradient start — website: `primary_dark`
|
||||
final Color controlsGradientStart;
|
||||
/// Controls bar / card surface gradient end — website: `primary_dark`
|
||||
final Color controlsGradientEnd;
|
||||
/// Shadow color for elevated surfaces
|
||||
final Color controlsShadow;
|
||||
final Color statusText;
|
||||
/// Website: `text` → body text
|
||||
final Color bodyText;
|
||||
/// Inner card background overlay — derived from `primary_dark` / `primary_light`
|
||||
final Color cardSurface;
|
||||
/// Inner card border — derived from `primary_dark` / `primary_light`
|
||||
final Color cardBorder;
|
||||
/// Website: `success` → live indicator, success states
|
||||
final Color successColor;
|
||||
/// Website: `danger` → error states
|
||||
final Color dangerColor;
|
||||
}
|
||||
|
||||
class AppThemeBusinessObject {
|
||||
@@ -47,17 +72,17 @@ class AppThemeBusinessObject {
|
||||
}
|
||||
|
||||
static ThemeData lightTheme() {
|
||||
final ColorScheme scheme =
|
||||
ColorScheme.fromSeed(
|
||||
seedColor: lightColors.primarySeed,
|
||||
brightness: Brightness.light,
|
||||
).copyWith(
|
||||
primary: lightColors.primarySeed,
|
||||
secondary: lightColors.secondarySeed,
|
||||
tertiary: const Color(0xFF2C85E1),
|
||||
surface: const Color(0xFFFFFBF7),
|
||||
onSurface: lightColors.statusText,
|
||||
);
|
||||
final ColorScheme scheme = ColorScheme.light(
|
||||
brightness: Brightness.light,
|
||||
primary: lightColors.headingColor,
|
||||
onPrimary: lightColors.textOnDark,
|
||||
secondary: lightColors.accentColor,
|
||||
onSecondary: lightColors.textOnDark,
|
||||
surface: lightColors.shellSurface,
|
||||
onSurface: lightColors.bodyText,
|
||||
error: lightColors.dangerColor,
|
||||
onError: lightColors.textOnDark,
|
||||
);
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
@@ -77,17 +102,17 @@ class AppThemeBusinessObject {
|
||||
}
|
||||
|
||||
static ThemeData darkTheme() {
|
||||
final ColorScheme scheme =
|
||||
ColorScheme.fromSeed(
|
||||
seedColor: darkColors.primarySeed,
|
||||
brightness: Brightness.dark,
|
||||
).copyWith(
|
||||
primary: darkColors.primarySeed,
|
||||
secondary: darkColors.secondarySeed,
|
||||
tertiary: const Color(0xFF4E97E8),
|
||||
surface: const Color(0xFF111A27),
|
||||
onSurface: darkColors.statusText,
|
||||
);
|
||||
final ColorScheme scheme = ColorScheme.dark(
|
||||
brightness: Brightness.dark,
|
||||
primary: darkColors.headingColor,
|
||||
onPrimary: darkColors.textOnDark,
|
||||
secondary: darkColors.accentColor,
|
||||
onSecondary: darkColors.textOnDark,
|
||||
surface: darkColors.shellSurface,
|
||||
onSurface: darkColors.bodyText,
|
||||
error: darkColors.dangerColor,
|
||||
onError: darkColors.textOnDark,
|
||||
);
|
||||
|
||||
return ThemeData(
|
||||
useMaterial3: true,
|
||||
|
||||
@@ -58,7 +58,7 @@ class LiveInfoPanel extends StatelessWidget {
|
||||
children: [
|
||||
Icon(
|
||||
Icons.graphic_eq_rounded,
|
||||
color: themeColors.statusText,
|
||||
color: themeColors.textOnDarkSecondary,
|
||||
size: 20,
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -67,7 +67,7 @@ class LiveInfoPanel extends StatelessWidget {
|
||||
'Live Studio Feed',
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w800,
|
||||
color: themeColors.statusText,
|
||||
color: themeColors.textOnDark,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -94,7 +94,9 @@ class LiveInfoPanel extends StatelessWidget {
|
||||
child: TrackCard(
|
||||
label: 'Now Playing',
|
||||
track: current,
|
||||
titleColor: themeColors.statusText,
|
||||
titleColor: themeColors.textOnDark,
|
||||
cardSurface: themeColors.cardSurface,
|
||||
cardBorder: themeColors.cardBorder,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -102,7 +104,9 @@ class LiveInfoPanel extends StatelessWidget {
|
||||
child: TrackCard(
|
||||
label: 'Coming Next',
|
||||
track: next,
|
||||
titleColor: themeColors.statusText,
|
||||
titleColor: themeColors.textOnDark,
|
||||
cardSurface: themeColors.cardSurface,
|
||||
cardBorder: themeColors.cardBorder,
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -113,14 +117,18 @@ class LiveInfoPanel extends StatelessWidget {
|
||||
label: 'On Air Show',
|
||||
show: currentShow,
|
||||
sourceTimezone: snapshot?.timezone,
|
||||
titleColor: themeColors.statusText,
|
||||
titleColor: themeColors.textOnDarkSecondary,
|
||||
cardSurface: themeColors.cardSurface,
|
||||
cardBorder: themeColors.cardBorder,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
ShowCard(
|
||||
label: 'Up Next Show',
|
||||
show: nextShow,
|
||||
sourceTimezone: snapshot?.timezone,
|
||||
titleColor: themeColors.statusText,
|
||||
titleColor: themeColors.textOnDarkSecondary,
|
||||
cardSurface: themeColors.cardSurface,
|
||||
cardBorder: themeColors.cardBorder,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
|
||||
+2
-2
@@ -400,7 +400,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
style: theme.textTheme.headlineMedium?.copyWith(
|
||||
fontWeight: FontWeight.w900,
|
||||
letterSpacing: 0.4,
|
||||
color: themeColors.statusText,
|
||||
color: themeColors.headingColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -469,7 +469,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver {
|
||||
_playbackStatusLabel(),
|
||||
style: theme.textTheme.titleSmall?.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: themeColors.statusText,
|
||||
color: themeColors.textOnDark,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
+13
-4
@@ -10,12 +10,16 @@ class ShowCard extends StatelessWidget {
|
||||
required this.show,
|
||||
required this.sourceTimezone,
|
||||
required this.titleColor,
|
||||
required this.cardSurface,
|
||||
required this.cardBorder,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final LiveInfoShowInfo? show;
|
||||
final String? sourceTimezone;
|
||||
final Color titleColor;
|
||||
final Color cardSurface;
|
||||
final Color cardBorder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -23,8 +27,8 @@ class ShowCard extends StatelessWidget {
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
color: Colors.black.withValues(alpha: 0.06),
|
||||
border: Border.all(color: Colors.black.withValues(alpha: 0.08)),
|
||||
color: cardSurface,
|
||||
border: Border.all(color: cardBorder),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -37,7 +41,10 @@ class ShowCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodyMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
).textTheme.bodyMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: titleColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
@@ -46,7 +53,9 @@ class ShowCard extends StatelessWidget {
|
||||
show?.starts,
|
||||
sourceTimezone: sourceTimezone,
|
||||
),
|
||||
style: Theme.of(context).textTheme.labelSmall,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.labelSmall?.copyWith(color: titleColor),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
+17
-5
@@ -9,11 +9,15 @@ class TrackCard extends StatelessWidget {
|
||||
required this.label,
|
||||
required this.track,
|
||||
required this.titleColor,
|
||||
required this.cardSurface,
|
||||
required this.cardBorder,
|
||||
});
|
||||
|
||||
final String label;
|
||||
final LiveInfoTrackInfo? track;
|
||||
final Color titleColor;
|
||||
final Color cardSurface;
|
||||
final Color cardBorder;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@@ -24,9 +28,9 @@ class TrackCard extends StatelessWidget {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: 0.08),
|
||||
color: cardSurface,
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
border: Border.all(color: Colors.black.withValues(alpha: 0.12)),
|
||||
border: Border.all(color: cardBorder),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
@@ -45,21 +49,29 @@ class TrackCard extends StatelessWidget {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.titleMedium?.copyWith(fontWeight: FontWeight.w700),
|
||||
).textTheme.titleMedium?.copyWith(
|
||||
fontWeight: FontWeight.w700,
|
||||
color: titleColor,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
subtitle.isEmpty ? 'No metadata provided' : subtitle,
|
||||
maxLines: 6,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.bodySmall?.copyWith(color: titleColor),
|
||||
),
|
||||
const Spacer(),
|
||||
Text(
|
||||
window,
|
||||
style: Theme.of(
|
||||
context,
|
||||
).textTheme.labelMedium?.copyWith(fontWeight: FontWeight.w600),
|
||||
).textTheme.labelMedium?.copyWith(
|
||||
fontWeight: FontWeight.w600,
|
||||
color: titleColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user