/
opt
/
canhelp
/
apps
/
mobile
/
lib
/
theme
/
/opt/canhelp/apps/mobile/lib/theme
mkdir
upload
Name
Size
Mode
Actions
app_theme.dart
17852
0644
edit
dl
rm
Edit:
/opt/canhelp/apps/mobile/lib/theme/app_theme.dart
(17852B)
import 'package:flutter/material.dart'; class AppTheme { AppTheme._(); // ─── Brand palette (Green) ─── static const primary = Color(0xFF22C55E); static const primaryDark = Color(0xFF16A34A); static const primaryLight = Color(0xFFF0FDF4); static const primaryContainer = Color(0xFFDCFCE7); // ─── Slate surface palette ─── static const background = Color(0xFFF1F5F9); // slate-100 static const surface = Color(0xFFFFFFFF); static const surfaceVariant = Color(0xFFF8FAFC); // slate-50 (input fill) static const border = Color(0xFFE2E8F0); // slate-200 // ─── Text (Slate) ─── static const textPrimary = Color(0xFF0F172A); // slate-900 static const textSecondary = Color(0xFF64748B); // slate-500 static const textHint = Color(0xFF94A3B8); // slate-400 // ─── Semantic status ─── static const success = Color(0xFF16A34A); static const successLight = Color(0xFFDCFCE7); static const warning = Color(0xFFD97706); static const warningLight = Color(0xFFFEF3C7); static const danger = Color(0xFFDC2626); static const dangerLight = Color(0xFFFEE2E2); // ─── Extra accents ─── static const emerald = Color(0xFF10B981); // online / verified static const amber = Color(0xFFF59E0B); // star rating static const ratingText = Color(0xFFCA8A04); // Yellow-600 – star-rating text // ─── Amber shades (for confidential/warning blocks) ─── static const amber50 = Color(0xFFFFFBEB); static const amber200 = Color(0xFFFDE68A); static const amber700 = Color(0xFFB45309); static const amber900 = Color(0xFF92400E); static const dangerBorder = Color(0xFFFCA5A5); // ─── Category colors ─── static const Map<String, Color> _categoryColors = { 'cleaning': Color(0xFF22C55E), 'home-cleaning': Color(0xFF22C55E), 'repairs': Color(0xFFEF4444), 'plumbing': Color(0xFF3B82F6), 'electrical': Color(0xFFF59E0B), 'moving': Color(0xFF8B5CF6), 'tutoring': Color(0xFF06B6D4), 'english': Color(0xFF06B6D4), 'math': Color(0xFF06B6D4), 'beauty': Color(0xFFEC4899), 'it': Color(0xFF6366F1), 'it_support': Color(0xFF6366F1), 'design': Color(0xFF8B5CF6), 'events': Color(0xFFEC4899), 'pets': Color(0xFF10B981), 'auto': Color(0xFF6366F1), 'legal': Color(0xFF0EA5E9), 'accounting': Color(0xFF14B8A6), 'tech-repair': Color(0xFFF59E0B), 'photo-video': Color(0xFFEC4899), 'other': Color(0xFF64748B), }; static Color categoryColor(String? slug) => slug != null ? (_categoryColors[slug] ?? textSecondary) : textSecondary; static IconData categoryIcon(String? slug) { switch (slug) { case 'cleaning': case 'home-cleaning': return Icons.cleaning_services_rounded; case 'plumbing': return Icons.plumbing_rounded; case 'electrical': return Icons.electrical_services_rounded; case 'moving': return Icons.local_shipping_rounded; case 'tutoring': case 'english': case 'math': return Icons.school_rounded; case 'beauty': return Icons.face_retouching_natural_rounded; case 'it': case 'it_support': return Icons.computer_rounded; case 'design': return Icons.palette_rounded; case 'events': return Icons.celebration_rounded; case 'pets': return Icons.pets_rounded; case 'auto': return Icons.directions_car_rounded; case 'legal': return Icons.gavel_rounded; case 'accounting': return Icons.calculate_rounded; case 'tech-repair': return Icons.build_circle_rounded; case 'photo-video': return Icons.camera_alt_rounded; case 'repairs': return Icons.build_rounded; default: return Icons.category_rounded; } } // ─── Shadows ─── static const shadowColor = Color(0x0F000000); static const shadowColorLight = Color(0x08000000); // ─── Radii ─── static const double cardRadius = 16.0; static const double buttonRadius = 12.0; static const double inputRadius = 12.0; static const double chipRadius = 20.0; static const double smallRadius = 8.0; static const _bodyFont = 'DM Sans'; static const _displayFont = 'Outfit'; static const _fallbackFonts = ['.AppleSystemUIFont', 'Roboto', 'sans-serif']; static ThemeData get light { final colorScheme = ColorScheme( brightness: Brightness.light, primary: primary, onPrimary: Colors.white, primaryContainer: primaryContainer, onPrimaryContainer: primaryDark, secondary: const Color(0xFF7C3AED), onSecondary: Colors.white, secondaryContainer: const Color(0xFFEDE9FE), onSecondaryContainer: const Color(0xFF5B21B6), tertiary: const Color(0xFF0891B2), onTertiary: Colors.white, surface: surface, onSurface: textPrimary, onSurfaceVariant: textSecondary, error: danger, onError: Colors.white, outline: const Color(0xFFCBD5E1), outlineVariant: border, shadow: shadowColorLight, inverseSurface: const Color(0xFF1E293B), onInverseSurface: const Color(0xFFF8FAFC), inversePrimary: const Color(0xFF86EFAC), surfaceContainerHighest: background, ); return ThemeData( useMaterial3: true, colorScheme: colorScheme, scaffoldBackgroundColor: background, fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, textTheme: _buildTextTheme(colorScheme), appBarTheme: const AppBarTheme( centerTitle: false, elevation: 0, scrolledUnderElevation: 1, backgroundColor: primary, foregroundColor: Colors.white, surfaceTintColor: Colors.transparent, iconTheme: IconThemeData(color: Colors.white), actionsIconTheme: IconThemeData(color: Colors.white), titleTextStyle: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 20, fontWeight: FontWeight.w600, color: Colors.white, ), ), cardTheme: CardThemeData( elevation: 0, shadowColor: Colors.black.withValues(alpha: 0.06), surfaceTintColor: Colors.transparent, color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(cardRadius), side: const BorderSide(color: border), ), margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), ), elevatedButtonTheme: ElevatedButtonThemeData( style: ElevatedButton.styleFrom( elevation: 0, backgroundColor: primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(buttonRadius), ), textStyle: const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 16, fontWeight: FontWeight.w600, ), ), ), filledButtonTheme: FilledButtonThemeData( style: FilledButton.styleFrom( backgroundColor: primary, foregroundColor: Colors.white, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(buttonRadius), ), textStyle: const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 16, fontWeight: FontWeight.w600, ), ), ), outlinedButtonTheme: OutlinedButtonThemeData( style: OutlinedButton.styleFrom( foregroundColor: primary, padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(buttonRadius), ), side: const BorderSide(color: primary, width: 1.5), textStyle: const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 16, fontWeight: FontWeight.w600, ), ), ), textButtonTheme: TextButtonThemeData( style: TextButton.styleFrom( foregroundColor: primary, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(buttonRadius), ), textStyle: const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 15, fontWeight: FontWeight.w600, ), ), ), floatingActionButtonTheme: FloatingActionButtonThemeData( backgroundColor: primary, foregroundColor: Colors.white, elevation: 3, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(cardRadius), ), ), inputDecorationTheme: InputDecorationTheme( filled: true, fillColor: Colors.white, contentPadding: const EdgeInsets.symmetric( horizontal: 16, vertical: 14, ), border: OutlineInputBorder( borderRadius: BorderRadius.circular(inputRadius), borderSide: const BorderSide(color: border), ), enabledBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(inputRadius), borderSide: const BorderSide(color: border), ), focusedBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(inputRadius), borderSide: const BorderSide(color: primary, width: 2), ), errorBorder: OutlineInputBorder( borderRadius: BorderRadius.circular(inputRadius), borderSide: const BorderSide(color: danger), ), hintStyle: const TextStyle( color: textHint, fontWeight: FontWeight.w400, ), ), chipTheme: ChipThemeData( backgroundColor: background, selectedColor: primaryLight, labelStyle: const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 13, fontWeight: FontWeight.w500, ), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(chipRadius), ), side: BorderSide.none, padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), ), navigationBarTheme: NavigationBarThemeData( backgroundColor: Colors.white, indicatorColor: primaryLight, elevation: 2, surfaceTintColor: Colors.transparent, labelTextStyle: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 11, fontWeight: FontWeight.w600, color: primary, ); } return const TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 11, fontWeight: FontWeight.w400, color: textSecondary, ); }), iconTheme: WidgetStateProperty.resolveWith((states) { if (states.contains(WidgetState.selected)) { return const IconThemeData(color: primary); } return const IconThemeData(color: textSecondary); }), ), dividerTheme: const DividerThemeData( color: border, thickness: 1, space: 1, ), snackBarTheme: SnackBarThemeData( behavior: SnackBarBehavior.floating, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(buttonRadius), ), backgroundColor: const Color(0xFF1E293B), ), dialogTheme: DialogThemeData( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(cardRadius), ), surfaceTintColor: Colors.transparent, backgroundColor: Colors.white, ), bottomSheetTheme: const BottomSheetThemeData( backgroundColor: Colors.white, surfaceTintColor: Colors.transparent, showDragHandle: true, shape: RoundedRectangleBorder( borderRadius: BorderRadius.vertical(top: Radius.circular(20)), ), ), ); } static ThemeData get dark { final colorScheme = ColorScheme( brightness: Brightness.dark, primary: const Color(0xFF60A5FA), onPrimary: const Color(0xFF1E3A5F), primaryContainer: const Color(0xFF1D4ED8), onPrimaryContainer: const Color(0xFFBFDBFE), secondary: const Color(0xFFA78BFA), onSecondary: const Color(0xFF2E1065), secondaryContainer: const Color(0xFF5B21B6), onSecondaryContainer: const Color(0xFFEDE9FE), tertiary: const Color(0xFF22D3EE), onTertiary: const Color(0xFF164E63), surface: const Color(0xFF1C1B1F), onSurface: const Color(0xFFE6E1E5), onSurfaceVariant: const Color(0xFF9CA3AF), error: const Color(0xFFFCA5A5), onError: const Color(0xFF7F1D1D), outline: const Color(0xFF4B5563), outlineVariant: const Color(0xFF374151), shadow: Colors.black.withValues(alpha: 0.3), inverseSurface: const Color(0xFFE6E1E5), onInverseSurface: const Color(0xFF313033), inversePrimary: primary, surfaceContainerHighest: const Color(0xFF111827), ); return ThemeData( useMaterial3: true, colorScheme: colorScheme, scaffoldBackgroundColor: const Color(0xFF111827), fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, textTheme: _buildTextTheme(colorScheme), appBarTheme: AppBarTheme( centerTitle: false, elevation: 0, backgroundColor: const Color(0xFF1F2937), foregroundColor: colorScheme.onSurface, surfaceTintColor: Colors.transparent, ), cardTheme: CardThemeData( elevation: 0, color: const Color(0xFF1F2937), surfaceTintColor: Colors.transparent, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(cardRadius), side: const BorderSide(color: Color(0xFF374151)), ), ), ); } static TextTheme _buildTextTheme(ColorScheme scheme) { final onSurface = scheme.onSurface; final muted = scheme.onSurfaceVariant; return TextTheme( displayLarge: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 57, fontWeight: FontWeight.w700, letterSpacing: -0.25, color: onSurface, ), displayMedium: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 45, fontWeight: FontWeight.w700, color: onSurface, ), displaySmall: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 36, fontWeight: FontWeight.w600, color: onSurface, ), headlineLarge: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 32, fontWeight: FontWeight.w600, color: onSurface, ), headlineMedium: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 28, fontWeight: FontWeight.w600, color: onSurface, ), headlineSmall: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 24, fontWeight: FontWeight.w600, color: onSurface, ), titleLarge: TextStyle( fontFamily: _displayFont, fontFamilyFallback: _fallbackFonts, fontSize: 22, fontWeight: FontWeight.w600, color: onSurface, ), titleMedium: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 16, fontWeight: FontWeight.w600, color: onSurface, ), titleSmall: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 14, fontWeight: FontWeight.w600, color: onSurface, ), bodyLarge: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 16, fontWeight: FontWeight.w400, color: onSurface, ), bodyMedium: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 14, fontWeight: FontWeight.w400, color: muted, ), bodySmall: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 12, fontWeight: FontWeight.w400, color: muted, ), labelLarge: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 14, fontWeight: FontWeight.w600, color: onSurface, ), labelMedium: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 12, fontWeight: FontWeight.w500, color: muted, ), labelSmall: TextStyle( fontFamily: _bodyFont, fontFamilyFallback: _fallbackFonts, fontSize: 11, fontWeight: FontWeight.w500, color: muted, ), ); } }
Save
cmd:
run