app_theme.dart 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. import 'package:flutter/material.dart';
  2. import 'app_colors.dart';
  3. /// Material 3 theme built from the CarDash token set.
  4. class AppTheme {
  5. const AppTheme._();
  6. static ThemeData light() => _build(AppColors.light, Brightness.light);
  7. static ThemeData dark() => _build(AppColors.dark, Brightness.dark);
  8. static ThemeData _build(AppColors colors, Brightness brightness) {
  9. final scheme =
  10. ColorScheme.fromSeed(
  11. seedColor: colors.accent,
  12. brightness: brightness,
  13. ).copyWith(
  14. primary: colors.accent,
  15. onPrimary: colors.accentInk,
  16. primaryContainer: colors.accentSoft,
  17. onPrimaryContainer: colors.ink,
  18. secondary: colors.accent,
  19. onSecondary: colors.accentInk,
  20. secondaryContainer: colors.accentSoft,
  21. onSecondaryContainer: colors.ink,
  22. surface: colors.surface,
  23. onSurface: colors.ink,
  24. surfaceContainerHighest: colors.surfaceStrong,
  25. outline: colors.border,
  26. outlineVariant: colors.border,
  27. error: colors.danger,
  28. onError: Colors.white,
  29. );
  30. final textTheme = _textTheme(colors);
  31. return ThemeData(
  32. useMaterial3: true,
  33. brightness: brightness,
  34. colorScheme: scheme,
  35. scaffoldBackgroundColor: colors.canvas,
  36. canvasColor: colors.canvas,
  37. fontFamily: 'Manrope',
  38. textTheme: textTheme,
  39. iconTheme: IconThemeData(color: colors.ink, size: 22),
  40. dividerTheme: DividerThemeData(color: colors.border, thickness: 1),
  41. sliderTheme: SliderThemeData(
  42. activeTrackColor: colors.accent,
  43. inactiveTrackColor: colors.border,
  44. thumbColor: colors.accent,
  45. overlayColor: colors.accent.withValues(alpha: 0.14),
  46. trackHeight: 6,
  47. thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 10),
  48. overlayShape: const RoundSliderOverlayShape(overlayRadius: 22),
  49. trackShape: const RoundedRectSliderTrackShape(),
  50. tickMarkShape: SliderTickMarkShape.noTickMark,
  51. disabledActiveTrackColor: colors.border,
  52. disabledInactiveTrackColor: colors.border,
  53. disabledThumbColor: colors.inkFaint,
  54. ),
  55. inputDecorationTheme: InputDecorationTheme(
  56. filled: true,
  57. fillColor: colors.surfaceStrong,
  58. hintStyle: textTheme.bodyLarge?.copyWith(color: colors.inkFaint),
  59. contentPadding: const EdgeInsets.symmetric(
  60. horizontal: 20,
  61. vertical: 16,
  62. ),
  63. border: OutlineInputBorder(
  64. borderRadius: BorderRadius.circular(18),
  65. borderSide: BorderSide.none,
  66. ),
  67. enabledBorder: OutlineInputBorder(
  68. borderRadius: BorderRadius.circular(18),
  69. borderSide: BorderSide(color: colors.border),
  70. ),
  71. focusedBorder: OutlineInputBorder(
  72. borderRadius: BorderRadius.circular(18),
  73. borderSide: BorderSide(color: colors.accent, width: 1.4),
  74. ),
  75. ),
  76. snackBarTheme: SnackBarThemeData(
  77. backgroundColor: colors.ink,
  78. contentTextStyle: textTheme.bodyMedium?.copyWith(color: colors.canvas),
  79. behavior: SnackBarBehavior.floating,
  80. elevation: 0,
  81. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
  82. ),
  83. bottomSheetTheme: const BottomSheetThemeData(
  84. backgroundColor: Colors.transparent,
  85. surfaceTintColor: Colors.transparent,
  86. modalBarrierColor: Color(0x99000000),
  87. ),
  88. dialogTheme: DialogThemeData(
  89. backgroundColor: colors.surface,
  90. surfaceTintColor: Colors.transparent,
  91. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26)),
  92. ),
  93. pageTransitionsTheme: const PageTransitionsTheme(
  94. builders: {
  95. TargetPlatform.android: FadeUpwardsPageTransitionsBuilder(),
  96. TargetPlatform.linux: FadeUpwardsPageTransitionsBuilder(),
  97. },
  98. ),
  99. extensions: [colors],
  100. );
  101. }
  102. static TextTheme _textTheme(AppColors colors) {
  103. TextStyle style(
  104. double size,
  105. FontWeight weight,
  106. int variation, {
  107. double? height,
  108. double? letterSpacing,
  109. }) {
  110. return TextStyle(
  111. fontFamily: 'Manrope',
  112. fontSize: size,
  113. fontWeight: weight,
  114. height: height,
  115. letterSpacing: letterSpacing,
  116. color: colors.ink,
  117. fontVariations: [FontVariation('wght', variation.toDouble())],
  118. );
  119. }
  120. return TextTheme(
  121. displayLarge: style(
  122. 68,
  123. FontWeight.w600,
  124. 640,
  125. height: 0.96,
  126. letterSpacing: -2.6,
  127. ),
  128. displayMedium: style(
  129. 52,
  130. FontWeight.w600,
  131. 620,
  132. height: 1.0,
  133. letterSpacing: -1.8,
  134. ),
  135. displaySmall: style(
  136. 42,
  137. FontWeight.w600,
  138. 620,
  139. height: 1.05,
  140. letterSpacing: -1.2,
  141. ),
  142. headlineLarge: style(
  143. 34,
  144. FontWeight.w600,
  145. 620,
  146. height: 1.1,
  147. letterSpacing: -0.6,
  148. ),
  149. headlineMedium: style(
  150. 28,
  151. FontWeight.w600,
  152. 610,
  153. height: 1.15,
  154. letterSpacing: -0.4,
  155. ),
  156. headlineSmall: style(24, FontWeight.w600, 600, height: 1.2),
  157. titleLarge: style(20, FontWeight.w600, 600, height: 1.25),
  158. titleMedium: style(16, FontWeight.w600, 600, height: 1.3),
  159. titleSmall: style(14, FontWeight.w600, 600, height: 1.3),
  160. bodyLarge: style(16, FontWeight.w400, 440, height: 1.45),
  161. bodyMedium: style(14, FontWeight.w400, 440, height: 1.45),
  162. bodySmall: style(12, FontWeight.w400, 430, height: 1.4),
  163. labelLarge: style(14, FontWeight.w600, 600, height: 1.2),
  164. labelMedium: style(12, FontWeight.w500, 530, height: 1.25),
  165. labelSmall: style(11, FontWeight.w500, 520, height: 1.25),
  166. ).apply(bodyColor: colors.ink, displayColor: colors.ink);
  167. }
  168. }