diff --git a/src/assets/images/LandingArt.svg b/src/assets/images/LandingArt.svg index 31b319d..0b639e4 100644 --- a/src/assets/images/LandingArt.svg +++ b/src/assets/images/LandingArt.svg @@ -1,5 +1,7 @@ - - - - + + + + + + diff --git a/src/lib/common/themes/comfy_theme.dart b/src/lib/common/themes/comfy_theme.dart index 8a8558b..65ed540 100644 --- a/src/lib/common/themes/comfy_theme.dart +++ b/src/lib/common/themes/comfy_theme.dart @@ -1,5 +1,14 @@ import 'package:flutter/material.dart'; +// CONSTANTS +const Color background = Color(0xFF4A5B6E); +const Color surface = Color(0xFF425366); +const Color selected = Color(0xFFF8CDC6); +const Color unselected = Color(0xFF9EC1CC); +const Color text = Color(0xFFF5EFEE); +const Color hover = Color(0xFFF5EFEE); +const Color error = Color(0xFFC9465E); + @immutable class CustomPalette extends ThemeExtension { const CustomPalette({ @@ -60,66 +69,93 @@ class CustomPalette extends ThemeExtension { final comfyTheme = ThemeData( useMaterial3: true, colorScheme: ColorScheme.fromSeed( - seedColor: const Color(0xFFF8CDC6), - background: const Color(0xFF4A5B6E), + seedColor: selected, + background: background, ), appBarTheme: const AppBarTheme( elevation: 0, backgroundColor: Colors.transparent, - foregroundColor: Color(0xFF9EC1CC), + foregroundColor: unselected, titleTextStyle: TextStyle( - color: Color(0xFFF5EFEE), + color: text, fontSize: 22, fontWeight: FontWeight.w500, ), ), tabBarTheme: TabBarTheme( - labelColor: const Color(0xFFF8CDC6), - unselectedLabelColor: const Color(0xFF9EC1CC), + labelColor: selected, + unselectedLabelColor: unselected, indicator: const BoxDecoration(), splashFactory: NoSplash.splashFactory, overlayColor: MaterialStateProperty.all(Colors.transparent), ), textButtonTheme: TextButtonThemeData( style: ButtonStyle( - foregroundColor: - MaterialStateProperty.all(const Color(0xFFF8CDC6)), - overlayColor: MaterialStateProperty.all(const Color(0xFF425366)), + foregroundColor: MaterialStateProperty.all(selected), + overlayColor: MaterialStateProperty.all(surface), + ), + ), + filledButtonTheme: FilledButtonThemeData( + style: ButtonStyle( + backgroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.hovered)) { + return hover; + } else if (states.contains(MaterialState.pressed) || + states.contains(MaterialState.focused) || + states.contains(MaterialState.selected)) { + return selected; + } else { + return unselected; + } + }, + ), + foregroundColor: MaterialStateProperty.resolveWith( + (Set states) { + if (states.contains(MaterialState.hovered)) { + return surface; + } else if (states.contains(MaterialState.pressed) || + states.contains(MaterialState.focused) || + states.contains(MaterialState.selected)) { + return surface; + } else { + return text; + } + }, + ), ), ), cardTheme: const CardTheme( - elevation: 0, - color: Color(0xFF425366), - surfaceTintColor: Colors.transparent), + elevation: 0, color: surface, surfaceTintColor: Colors.transparent), progressIndicatorTheme: const ProgressIndicatorThemeData( - color: Color(0xFFF8CDC6), - linearTrackColor: Color(0xFF4A5B6E), + color: selected, + linearTrackColor: background, ), textTheme: const TextTheme( - displayLarge: TextStyle(color: Color(0xFFF5EFEE)), - displayMedium: TextStyle(color: Color(0xFFF5EFEE)), - displaySmall: TextStyle(color: Color(0xFFF5EFEE)), - headlineLarge: TextStyle(color: Color(0xFFF5EFEE)), - headlineMedium: TextStyle(color: Color(0xFFF5EFEE)), - headlineSmall: TextStyle(color: Color(0xFFF5EFEE)), - titleLarge: TextStyle(color: Color(0xFFF5EFEE)), - titleMedium: TextStyle(color: Color(0xFFF5EFEE)), - titleSmall: TextStyle(color: Color(0xFFF5EFEE)), - labelLarge: TextStyle(color: Color(0xFFF5EFEE)), - labelMedium: TextStyle(color: Color(0xFFF5EFEE)), - labelSmall: TextStyle(color: Color(0xFFF5EFEE)), - bodyLarge: TextStyle(color: Color(0xFFF5EFEE)), - bodyMedium: TextStyle(color: Color(0xFFF5EFEE)), - bodySmall: TextStyle(color: Color(0xFFF5EFEE)), + displayLarge: TextStyle(color: text), + displayMedium: TextStyle(color: text), + displaySmall: TextStyle(color: text), + headlineLarge: TextStyle(color: text), + headlineMedium: TextStyle(color: text), + headlineSmall: TextStyle(color: text), + titleLarge: TextStyle(color: text), + titleMedium: TextStyle(color: text), + titleSmall: TextStyle(color: text), + labelLarge: TextStyle(color: text), + labelMedium: TextStyle(color: text), + labelSmall: TextStyle(color: text), + bodyLarge: TextStyle(color: text), + bodyMedium: TextStyle(color: text), + bodySmall: TextStyle(color: text), ), extensions: const >[ CustomPalette( - background: Color(0xFF4A5B6E), - surface: Color(0xFF425366), - selected: Color(0xFFF8CDC6), - unselected: Color(0xFF9EC1CC), - text: Color(0xFFF5EFEE), - hover: Color(0xFFF5EFEE), - error: Color(0xFFC9465E), + background: background, + surface: surface, + selected: selected, + unselected: unselected, + text: text, + hover: hover, + error: error, ), ]); diff --git a/src/lib/features/authentication/landing_page.dart b/src/lib/features/authentication/landing_page.dart index 2ac2e4d..74bc18d 100644 --- a/src/lib/features/authentication/landing_page.dart +++ b/src/lib/features/authentication/landing_page.dart @@ -1,69 +1,64 @@ import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; +import '../../common/themes/comfy_theme.dart'; import 'google_provider.dart'; class LandingPage extends StatelessWidget { const LandingPage({Key? key}) : super(key: key); - // TODO clean up code - @override Widget build(BuildContext context) => Stack(children: [ - SvgPicture.asset( - 'assets/images/LandingArt.svg', - alignment: Alignment.bottomCenter, - width: MediaQuery.of(context).size.width, - height: MediaQuery.of(context).size.height, - ), + _buildBackgroundArt(context), Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - const Text( - 'Welcome To', - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.w500, - color: Color(0xff828282)), - ), - const SizedBox(height: 16), - const Text( - 'ASLearner', - style: TextStyle( - fontSize: 48, - fontWeight: FontWeight.w500, - color: Colors.white, - ), - ), - const SizedBox(height: 16), - const Text( - 'A spaced-repetition flashcard ASL learning app.\nLearn American Sign Language simply and effectively!', - textAlign: TextAlign.center, - style: TextStyle( - fontSize: 32, - fontWeight: FontWeight.w500, - color: Color(0xff828282), - ), - ), + _buildMotto(context), const SizedBox(height: 48), - ElevatedButton( - style: ElevatedButton.styleFrom( - side: const BorderSide(color: Color(0xFF1E1E1E)), - elevation: 10, - backgroundColor: const Color(0xFF292929), - padding: const EdgeInsets.all(10), - textStyle: const TextStyle(fontSize: 14), - minimumSize: const Size(240, 48)), - child: const Text('GET STARTED'), - onPressed: () { - final provider = - Provider.of(context, listen: false); - provider.googleLogin(); - }, - ), + _buildLoginButton(context), ], ), ), ]); + + Widget _buildLoginButton(BuildContext context) => FilledButton( + style: FilledButton.styleFrom(minimumSize: const Size(240, 48)), + child: const Text('GET STARTED'), + onPressed: () => context.read().googleLogin(), + ); + + Widget _buildMotto(BuildContext context) => RichText( + textAlign: TextAlign.center, + text: TextSpan( + text: 'Welcome To\n', + style: Theme.of(context).textTheme.displaySmall!.copyWith( + color: + Theme.of(context).extension()!.unselected), + children: [ + TextSpan( + text: 'ASLearner\n', + style: Theme.of(context).textTheme.displayLarge!.copyWith( + color: + Theme.of(context).extension()!.selected), + ), + TextSpan( + text: + 'A spaced-repetition flashcard ASL learning app.\nLearn American Sign Language simply and effectively!', + style: Theme.of(context).textTheme.displaySmall!.copyWith( + color: Theme.of(context) + .extension()! + .unselected)), + ]), + ); + + Widget _buildBackgroundArt(BuildContext context) => SvgPicture.asset( + 'assets/images/LandingArt.svg', + colorFilter: ColorFilter.mode( + Theme.of(context).extension()!.surface as Color, + BlendMode.srcATop), + alignment: Alignment.bottomCenter, + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height, + ); }