Implementation
static ThemeData lightThemeData(BuildContext context) {
// ================================
// BLACK & WHITE COLOR PALETTE
// ================================
// Primary Colors
const Color primaryBlack = Color(0xFF000000); // Primary color - Pure Black
const Color backgroundWhite = Color(0xFFFFFFFF); // Background - Pure White
// Grayscale Palette
const Color darkGray = Color(0xFF212121); // Dark text, headings
const Color mediumGray = Color(0xFF424242); // Secondary text
const Color gray = Color(0xFF757575); // Tertiary text, icons
const Color lightGray = Color(0xFF9E9E9E); // Hints, placeholders
const Color veryLightGray = Color(0xFFE0E0E0); // Borders, dividers
const Color extraLightGray = Color(0xFFF5F5F5); // Cards, surfaces
const Color scaffoldBackground = Color(0xFFFAFAFA); // Scaffold background
// Accent & Status Colors
const Color accentGray = Color(0xFF616161); // Accent elements
const Color errorRed = Color(0xFFD32F2F); // Error states
const Color errorRedLight = Color(0x66D32F2F); // Error states (light)
const Color successGreen = Color(0xFF388E3C); // Success states
const Color warningOrange = Color(0xFFF57C00); // Warning states
// Shadow & Overlay Colors
const Color shadowColor = Color(0x1A000000); // Subtle shadows
const Color overlayColor = Color(0x0A000000); // Hover/pressed states
const Color dividerColor = Color(0xFFEEEEEE); // Dividers
return ThemeData(
useMaterial3: true,
fontFamily: "Inter",
cardColor: backgroundWhite,
primaryColor: primaryBlack,
scaffoldBackgroundColor: scaffoldBackground,
colorScheme: ColorScheme.fromSeed(
seedColor: primaryBlack,
primary: primaryBlack,
onPrimary: backgroundWhite,
surface: backgroundWhite,
onSurface: darkGray,
background: backgroundWhite,
onBackground: darkGray,
error: errorRed,
onError: backgroundWhite,
outline: veryLightGray,
),
extensions: const <ThemeExtension<AppColors>>[
AppColors(
onSurface2: gray,
green: successGreen,
mediumGray: mediumGray,
lightGray: lightGray,
accentGray: accentGray,
warning: warningOrange,
),
],
dividerTheme: const DividerThemeData(thickness: 1, color: dividerColor),
textTheme: Theme.of(context).textTheme
// [BodyLarge] is used for the [TextField] value style
.copyWith(bodyLarge: const TextStyle(fontSize: 16).medium)
.apply(bodyColor: darkGray, displayColor: darkGray),
drawerTheme: const DrawerThemeData(backgroundColor: backgroundWhite),
bottomSheetTheme: const BottomSheetThemeData(
showDragHandle: true,
backgroundColor: backgroundWhite,
dragHandleColor: mediumGray,
),
inputDecorationTheme: InputDecorationTheme(
hintStyle: const TextStyle(color: lightGray, fontSize: 14).regular,
labelStyle: const TextStyle(color: gray, fontSize: 14).regular,
contentPadding: const EdgeInsetsDirectional.symmetric(
horizontal: 16,
vertical: 13,
),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: veryLightGray),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: veryLightGray),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: primaryBlack, width: 2),
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: errorRedLight),
),
focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: errorRed),
),
disabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(40),
borderSide: const BorderSide(color: extraLightGray),
),
),
textSelectionTheme: const TextSelectionThemeData(
cursorColor: primaryBlack,
),
outlinedButtonTheme: OutlinedButtonThemeData(
style: OutlinedButton.styleFrom(
minimumSize: const Size(100, 40),
backgroundColor: backgroundWhite,
visualDensity: VisualDensity.standard,
side: const BorderSide(color: primaryBlack),
foregroundColor: primaryBlack,
),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
elevation: 2,
visualDensity: VisualDensity.standard,
shadowColor: shadowColor,
backgroundColor: primaryBlack,
foregroundColor: backgroundWhite,
minimumSize: const Size(double.infinity, 54),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
),
),
),
navigationBarTheme: NavigationBarThemeData(
height: 65,
backgroundColor: backgroundWhite,
surfaceTintColor: backgroundWhite,
indicatorColor: overlayColor,
labelTextStyle: WidgetStateProperty.resolveWith<TextStyle?>((
Set<WidgetState> states,
) {
if (states.contains(WidgetState.selected)) {
return const TextStyle(color: primaryBlack).semiBold;
}
return const TextStyle(color: gray).semiBold;
}),
),
navigationRailTheme: NavigationRailThemeData(
minWidth: 110,
backgroundColor: backgroundWhite,
indicatorColor: overlayColor,
selectedIconTheme: const IconThemeData(color: primaryBlack),
unselectedIconTheme: const IconThemeData(color: gray),
unselectedLabelTextStyle: const TextStyle(color: gray).semiBold,
selectedLabelTextStyle: const TextStyle(color: primaryBlack).semiBold,
),
appBarTheme: AppBarTheme(
scrolledUnderElevation: 0,
backgroundColor: backgroundWhite,
iconTheme: const IconThemeData(color: primaryBlack),
titleTextStyle: const TextStyle(
fontSize: 16,
color: primaryBlack,
).semiBold,
),
// dialogTheme: DialogTheme(
// surfaceTintColor: Colors.white,
// shape: RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(24),
// ),
// ),
);
}