Files
flutter/lib/app/theme/mapflow_theme.dart
Ruslan Bakiev 8c23e878bb
Build and deploy Flutter Web / build (push) Successful in 4m44s
Apply dark restaurant theme
2026-06-22 11:16:24 +07:00

209 lines
7.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(0xFF15111D),
mapPanelBorder: Color(0xFF2F263D),
mapShadow: Color(0x99000000),
danger: Color(0xFFFF2D75),
onDark: Colors.white,
darkSurface: Color(0xFF05030B),
darkSurfaceAlt: Color(0xFF15111D),
voiceAccent: Color(0xFFFF2D75),
voiceAccentSoft: Color(0xFFFF8BB5),
onVoiceControl: Color(0xFF090613),
snowflakeLine: Color(0xFF3B304B),
snowflakeNode: Color(0xFF67567E),
snowflakeCenter: Color(0xFFFF2D75),
snowflakeLabel: Color(0xFFCFC1DE),
imageScrim: Color(0xCC000000),
panelRadius: 8,
);
static ThemeData dark() {
return FlexThemeData.dark(
useMaterial3: true,
colors: const FlexSchemeColor(
primary: Color(0xFFFF2D75),
primaryContainer: Color(0xFF5B1432),
secondary: Color(0xFFB86BFF),
secondaryContainer: Color(0xFF3E205A),
tertiary: Color(0xFFFFB86B),
tertiaryContainer: Color(0xFF4F2D13),
appBarColor: Color(0xFF05030B),
error: Color(0xFFFFB4AB),
),
scaffoldBackground: tokens.darkSurface,
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(0xFF05030B),
foregroundColor: Colors.white,
surfaceTintColor: Colors.transparent,
),
bottomSheetTheme: const BottomSheetThemeData(
backgroundColor: Color(0xFF15111D),
modalBackgroundColor: Color(0xFF15111D),
surfaceTintColor: Colors.transparent,
dragHandleColor: Color(0xFF8F7AA7),
),
cardTheme: CardThemeData(
elevation: 0,
color: tokens.mapPanel,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(tokens.panelRadius),
side: BorderSide(color: tokens.mapPanelBorder),
),
),
dialogTheme: const DialogThemeData(
backgroundColor: Color(0xFF15111D),
surfaceTintColor: Colors.transparent,
),
popupMenuTheme: PopupMenuThemeData(
color: tokens.mapPanel,
surfaceTintColor: Colors.transparent,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(tokens.panelRadius),
side: BorderSide(color: tokens.mapPanelBorder),
),
),
chipTheme: ChipThemeData(
backgroundColor: tokens.mapPanel,
selectedColor: const Color(0xFF5B1432),
disabledColor: const Color(0xFF211A2B),
secondarySelectedColor: const Color(0xFF5B1432),
labelStyle: const TextStyle(color: Color(0xFFF6ECFF)),
secondaryLabelStyle: const TextStyle(color: Colors.white),
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>()!;
}
}