diff --git a/lib/screens/about_screen.dart b/lib/screens/about_screen.dart index 1e5dcdde..30884476 100644 --- a/lib/screens/about_screen.dart +++ b/lib/screens/about_screen.dart @@ -455,7 +455,7 @@ class _ThemeSelectorSheet extends StatelessWidget { width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), diff --git a/lib/screens/drinks_screen.dart b/lib/screens/drinks_screen.dart index c58fa50f..79fd8d41 100644 --- a/lib/screens/drinks_screen.dart +++ b/lib/screens/drinks_screen.dart @@ -690,7 +690,7 @@ class _CategoryFilterSheet extends StatelessWidget { width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), @@ -774,7 +774,7 @@ class _SortOptionsSheet extends StatelessWidget { width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), @@ -873,7 +873,7 @@ class _StyleFilterSheet extends StatelessWidget { width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), diff --git a/lib/widgets/drink_list_section.dart b/lib/widgets/drink_list_section.dart index 9e873caa..ef3a68fa 100644 --- a/lib/widgets/drink_list_section.dart +++ b/lib/widgets/drink_list_section.dart @@ -164,13 +164,13 @@ class _DrinkCardWithSubtitle extends StatelessWidget { Icon( Icons.info_outline, size: 14, - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.6), + color: theme.colorScheme.onSurface, ), const SizedBox(width: 4), Text( subtitle, style: theme.textTheme.bodySmall?.copyWith( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.6), + color: theme.colorScheme.onSurface, fontStyle: FontStyle.italic, ), ), diff --git a/lib/widgets/festival_menu_sheets.dart b/lib/widgets/festival_menu_sheets.dart index 4bdc537d..17c3d05b 100644 --- a/lib/widgets/festival_menu_sheets.dart +++ b/lib/widgets/festival_menu_sheets.dart @@ -76,10 +76,11 @@ class FestivalSelectorSheet extends StatelessWidget { children: [ Center( child: Container( + key: const Key('festival_selector_drag_handle'), width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), @@ -482,10 +483,11 @@ class SettingsSheet extends StatelessWidget { children: [ Center( child: Container( + key: const Key('settings_sheet_drag_handle'), width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), @@ -542,10 +544,11 @@ class ThemeSelectorSheet extends StatelessWidget { children: [ Center( child: Container( + key: const Key('theme_selector_sheet_drag_handle'), width: 32, height: 4, decoration: BoxDecoration( - color: theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.4), + color: theme.colorScheme.onSurfaceVariant, borderRadius: BorderRadius.circular(2), ), ), diff --git a/lib/widgets/overflow_menu.dart b/lib/widgets/overflow_menu.dart index 8f211908..37dbd00e 100644 --- a/lib/widgets/overflow_menu.dart +++ b/lib/widgets/overflow_menu.dart @@ -9,6 +9,9 @@ import 'festival_menu_sheets.dart'; /// - Settings /// - About page Widget buildOverflowMenu(BuildContext context) { + final theme = Theme.of(context); + final menuContentColor = theme.colorScheme.onSurface; + return Semantics( label: 'Menu', hint: 'Double tap to open menu', @@ -17,14 +20,23 @@ Widget buildOverflowMenu(BuildContext context) { icon: const Icon(Icons.more_vert), tooltip: 'Menu', onSelected: (value) => _handleMenuSelection(context, value), - itemBuilder: (context) => const [ + itemBuilder: (context) => [ PopupMenuItem( value: 'festivals', child: Row( children: [ - ExcludeSemantics(child: Icon(Icons.festival)), - SizedBox(width: 12), - Expanded(child: Text('Browse Festivals')), + ExcludeSemantics( + child: Icon(Icons.festival, color: menuContentColor), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + 'Browse Festivals', + style: theme.textTheme.bodyLarge?.copyWith( + color: menuContentColor, + ), + ), + ), ], ), ), @@ -32,9 +44,18 @@ Widget buildOverflowMenu(BuildContext context) { value: 'settings', child: Row( children: [ - ExcludeSemantics(child: Icon(Icons.settings)), - SizedBox(width: 12), - Expanded(child: Text('Settings')), + ExcludeSemantics( + child: Icon(Icons.settings, color: menuContentColor), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + 'Settings', + style: theme.textTheme.bodyLarge?.copyWith( + color: menuContentColor, + ), + ), + ), ], ), ), @@ -42,9 +63,18 @@ Widget buildOverflowMenu(BuildContext context) { value: 'about', child: Row( children: [ - ExcludeSemantics(child: Icon(Icons.info_outline)), - SizedBox(width: 12), - Expanded(child: Text('About')), + ExcludeSemantics( + child: Icon(Icons.info_outline, color: menuContentColor), + ), + const SizedBox(width: 12), + Expanded( + child: Text( + 'About', + style: theme.textTheme.bodyLarge?.copyWith( + color: menuContentColor, + ), + ), + ), ], ), ), diff --git a/lib/widgets/star_rating.dart b/lib/widgets/star_rating.dart index 49a2241e..d0ade6e9 100644 --- a/lib/widgets/star_rating.dart +++ b/lib/widgets/star_rating.dart @@ -35,7 +35,7 @@ class StarRating extends StatelessWidget { Widget build(BuildContext context) { final theme = Theme.of(context); final active = activeColor ?? Colors.amber; - final inactive = inactiveColor ?? theme.colorScheme.onSurfaceVariant.withValues(alpha: 0.3); + final inactive = inactiveColor ?? theme.colorScheme.onSurfaceVariant; final ratingValue = rating ?? 0; final semanticLabel = isEditable ? 'Rate this drink' : 'Rating'; diff --git a/test/widgets/festival_menu_sheets_test.dart b/test/widgets/festival_menu_sheets_test.dart index 31c18a1b..b3a6be80 100644 --- a/test/widgets/festival_menu_sheets_test.dart +++ b/test/widgets/festival_menu_sheets_test.dart @@ -2,6 +2,7 @@ import 'package:cambridge_beer_festival/domain/repositories/repositories.dart'; import 'package:cambridge_beer_festival/models/models.dart'; import 'package:cambridge_beer_festival/providers/beer_provider.dart'; import 'package:cambridge_beer_festival/services/services.dart'; +import 'package:cambridge_beer_festival/app_theme.dart'; import 'package:cambridge_beer_festival/widgets/widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -65,8 +66,9 @@ void main() { await provider.initialize(); }); - Widget buildTestWidget() { + Widget buildTestWidget({ThemeData? theme}) { return MaterialApp( + theme: theme, home: Scaffold( body: ChangeNotifierProvider.value( value: provider, @@ -124,6 +126,18 @@ void main() { expect(semantics.properties.label, contains('Test Beer Festival 2024')); expect(semantics.properties.button, isTrue); }); + + testWidgets('uses high-contrast drag handle color in light theme', (tester) async { + final lightTheme = buildAppTheme(Brightness.light); + await tester.pumpWidget(buildTestWidget(theme: lightTheme)); + + final handleContainer = tester.widget( + find.byKey(const Key('festival_selector_drag_handle')), + ); + final decoration = handleContainer.decoration! as BoxDecoration; + + expect(decoration.color, lightTheme.colorScheme.onSurfaceVariant); + }); }); group('FestivalCard', () { @@ -250,8 +264,9 @@ void main() { await provider.initialize(); }); - Widget buildTestWidget() { + Widget buildTestWidget({ThemeData? theme}) { return MaterialApp( + theme: theme, home: Scaffold( body: ChangeNotifierProvider.value( value: provider, @@ -274,6 +289,18 @@ void main() { expect(find.text('System mode'), findsOneWidget); expect(find.byIcon(Icons.brightness_auto), findsOneWidget); }); + + testWidgets('uses high-contrast drag handle color in light theme', (tester) async { + final lightTheme = buildAppTheme(Brightness.light); + await tester.pumpWidget(buildTestWidget(theme: lightTheme)); + + final handleContainer = tester.widget( + find.byKey(const Key('settings_sheet_drag_handle')), + ); + final decoration = handleContainer.decoration! as BoxDecoration; + + expect(decoration.color, lightTheme.colorScheme.onSurfaceVariant); + }); }); group('ThemeSelectorSheet', () { @@ -309,8 +336,9 @@ void main() { await provider.initialize(); }); - Widget buildTestWidget() { + Widget buildTestWidget({ThemeData? theme}) { return MaterialApp( + theme: theme, home: Scaffold( body: ChangeNotifierProvider.value( value: provider, @@ -353,5 +381,17 @@ void main() { expect(provider.themeMode, ThemeMode.dark); }); + + testWidgets('uses high-contrast drag handle color in light theme', (tester) async { + final lightTheme = buildAppTheme(Brightness.light); + await tester.pumpWidget(buildTestWidget(theme: lightTheme)); + + final handleContainer = tester.widget( + find.byKey(const Key('theme_selector_sheet_drag_handle')), + ); + final decoration = handleContainer.decoration! as BoxDecoration; + + expect(decoration.color, lightTheme.colorScheme.onSurfaceVariant); + }); }); } diff --git a/test/widgets/overflow_menu_test.dart b/test/widgets/overflow_menu_test.dart index 8c1e4bde..a772cca6 100644 --- a/test/widgets/overflow_menu_test.dart +++ b/test/widgets/overflow_menu_test.dart @@ -1,4 +1,5 @@ import 'package:cambridge_beer_festival/widgets/widgets.dart'; +import 'package:cambridge_beer_festival/app_theme.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -115,6 +116,32 @@ void main() { ); }); + testWidgets('uses high-contrast menu item colors in light theme', (tester) async { + await tester.pumpWidget( + MaterialApp( + theme: buildAppTheme(Brightness.light), + home: Builder( + builder: (context) => Scaffold( + body: Center( + child: buildOverflowMenu(context), + ), + ), + ), + ), + ); + + await tester.tap(find.byIcon(Icons.more_vert)); + await tester.pumpAndSettle(); + + final expectedColor = buildAppTheme(Brightness.light).colorScheme.onSurface; + + final festivalIcon = tester.widget(find.byIcon(Icons.festival)); + expect(festivalIcon.color, expectedColor); + + final festivalText = tester.widget(find.text('Browse Festivals')); + expect(festivalText.style?.color, expectedColor); + }); + testWidgets('has proper tooltip', (tester) async { await tester.pumpWidget(buildMenuWidget()); diff --git a/test/widgets_test.dart b/test/widgets_test.dart index b1ba0795..f13461b8 100644 --- a/test/widgets_test.dart +++ b/test/widgets_test.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:cambridge_beer_festival/app_theme.dart'; import 'package:cambridge_beer_festival/widgets/widgets.dart'; void main() { @@ -195,6 +196,22 @@ void main() { expect(iconWidget.color, Colors.blue); }); + testWidgets('uses high-contrast default inactive color in light theme', (WidgetTester tester) async { + final lightTheme = buildAppTheme(Brightness.light); + await tester.pumpWidget( + MaterialApp( + theme: lightTheme, + home: const Scaffold( + body: StarRating(rating: 1), + ), + ), + ); + + final emptyStar = find.byIcon(Icons.star_border); + final iconWidget = tester.widget(emptyStar.first); + expect(iconWidget.color, lightTheme.colorScheme.onSurfaceVariant); + }); + testWidgets('tapping same star clears rating', (WidgetTester tester) async { int? selectedRating;