Files
flutter/lib/app/theme/mapflow_theme.dart
T
Ruslan Bakiev 479dc25847
Build and deploy Flutter Web / build (push) Successful in 2m15s
Move map visuals into theme tokens
2026-06-12 14:41:11 +07:00

185 lines
6.0 KiB
Dart

import 'package:flex_color_scheme/flex_color_scheme.dart';
import 'package:flutter/material.dart';
@immutable
class MapflowThemeTokens extends ThemeExtension<MapflowThemeTokens> {
const MapflowThemeTokens({
required this.mapPanel,
required this.mapPanelBorder,
required this.mapShadow,
required this.danger,
required this.onDark,
required this.darkSurface,
required this.darkSurfaceAlt,
required this.voiceAccent,
required this.voiceAccentSoft,
required this.onVoiceControl,
required this.snowflakeLine,
required this.snowflakeNode,
required this.snowflakeCenter,
required this.snowflakeLabel,
required this.imageScrim,
required this.panelRadius,
});
final Color mapPanel;
final Color mapPanelBorder;
final Color mapShadow;
final Color danger;
final Color onDark;
final Color darkSurface;
final Color darkSurfaceAlt;
final Color voiceAccent;
final Color voiceAccentSoft;
final Color onVoiceControl;
final Color snowflakeLine;
final Color snowflakeNode;
final Color snowflakeCenter;
final Color snowflakeLabel;
final Color imageScrim;
final double panelRadius;
@override
MapflowThemeTokens copyWith({
Color? mapPanel,
Color? mapPanelBorder,
Color? mapShadow,
Color? danger,
Color? onDark,
Color? darkSurface,
Color? darkSurfaceAlt,
Color? voiceAccent,
Color? voiceAccentSoft,
Color? onVoiceControl,
Color? snowflakeLine,
Color? snowflakeNode,
Color? snowflakeCenter,
Color? snowflakeLabel,
Color? imageScrim,
double? panelRadius,
}) {
return MapflowThemeTokens(
mapPanel: mapPanel ?? this.mapPanel,
mapPanelBorder: mapPanelBorder ?? this.mapPanelBorder,
mapShadow: mapShadow ?? this.mapShadow,
danger: danger ?? this.danger,
onDark: onDark ?? this.onDark,
darkSurface: darkSurface ?? this.darkSurface,
darkSurfaceAlt: darkSurfaceAlt ?? this.darkSurfaceAlt,
voiceAccent: voiceAccent ?? this.voiceAccent,
voiceAccentSoft: voiceAccentSoft ?? this.voiceAccentSoft,
onVoiceControl: onVoiceControl ?? this.onVoiceControl,
snowflakeLine: snowflakeLine ?? this.snowflakeLine,
snowflakeNode: snowflakeNode ?? this.snowflakeNode,
snowflakeCenter: snowflakeCenter ?? this.snowflakeCenter,
snowflakeLabel: snowflakeLabel ?? this.snowflakeLabel,
imageScrim: imageScrim ?? this.imageScrim,
panelRadius: panelRadius ?? this.panelRadius,
);
}
@override
MapflowThemeTokens lerp(
covariant ThemeExtension<MapflowThemeTokens>? other,
double t,
) {
if (other is! MapflowThemeTokens) {
return this;
}
return MapflowThemeTokens(
mapPanel: Color.lerp(mapPanel, other.mapPanel, t)!,
mapPanelBorder: Color.lerp(mapPanelBorder, other.mapPanelBorder, t)!,
mapShadow: Color.lerp(mapShadow, other.mapShadow, t)!,
danger: Color.lerp(danger, other.danger, t)!,
onDark: Color.lerp(onDark, other.onDark, t)!,
darkSurface: Color.lerp(darkSurface, other.darkSurface, t)!,
darkSurfaceAlt: Color.lerp(darkSurfaceAlt, other.darkSurfaceAlt, t)!,
voiceAccent: Color.lerp(voiceAccent, other.voiceAccent, t)!,
voiceAccentSoft: Color.lerp(voiceAccentSoft, other.voiceAccentSoft, t)!,
onVoiceControl: Color.lerp(onVoiceControl, other.onVoiceControl, t)!,
snowflakeLine: Color.lerp(snowflakeLine, other.snowflakeLine, t)!,
snowflakeNode: Color.lerp(snowflakeNode, other.snowflakeNode, t)!,
snowflakeCenter: Color.lerp(snowflakeCenter, other.snowflakeCenter, t)!,
snowflakeLabel: Color.lerp(snowflakeLabel, other.snowflakeLabel, t)!,
imageScrim: Color.lerp(imageScrim, other.imageScrim, t)!,
panelRadius: lerpDouble(panelRadius, other.panelRadius, t),
);
}
}
class MapflowTheme {
const MapflowTheme._();
static const tokens = MapflowThemeTokens(
mapPanel: Color(0xFFFFFBF5),
mapPanelBorder: Color(0xFFE0D8CA),
mapShadow: Color(0x33000000),
danger: Color(0xFFE11D48),
onDark: Colors.white,
darkSurface: Color(0xFF05030B),
darkSurfaceAlt: Color(0xFF15111D),
voiceAccent: Color(0xFFFF2D75),
voiceAccentSoft: Color(0xFFFF7A90),
onVoiceControl: Color(0xFF090613),
snowflakeLine: Color(0xFFE6DDD2),
snowflakeNode: Color(0xFFDED3C7),
snowflakeCenter: Color(0xFF241B18),
snowflakeLabel: Color(0xFF746A60),
imageScrim: Color(0xCC000000),
panelRadius: 8,
);
static ThemeData light() {
return FlexThemeData.light(
useMaterial3: true,
colors: const FlexSchemeColor(
primary: Color(0xFF0F766E),
primaryContainer: Color(0xFFBFE7DF),
secondary: Color(0xFFE11D48),
secondaryContainer: Color(0xFFFFD9E1),
tertiary: Color(0xFF7C3AED),
tertiaryContainer: Color(0xFFE9DDFF),
appBarColor: Color(0xFFF7F3EA),
error: Color(0xFFB3261E),
),
scaffoldBackground: const Color(0xFFF7F3EA),
surface: tokens.mapPanel,
subThemesData: const FlexSubThemesData(
defaultRadius: 8,
inputDecoratorRadius: 8,
cardRadius: 8,
chipRadius: 8,
filledButtonRadius: 8,
),
fontFamily: 'SF Pro Display',
extensions: const [tokens],
).copyWith(
appBarTheme: const AppBarTheme(
backgroundColor: Color(0xFFF7F3EA),
foregroundColor: Color(0xFF17211D),
surfaceTintColor: Colors.transparent,
),
cardTheme: CardThemeData(
elevation: 0,
color: tokens.mapPanel,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(tokens.panelRadius),
side: BorderSide(color: tokens.mapPanelBorder),
),
),
chipTheme: ChipThemeData(
shape: StadiumBorder(side: BorderSide(color: tokens.mapPanelBorder)),
),
);
}
}
double lerpDouble(double a, double b, double t) => a + (b - a) * t;
extension MapflowThemeContext on BuildContext {
MapflowThemeTokens get mapflowTokens {
return Theme.of(this).extension<MapflowThemeTokens>()!;
}
}