Skip to content

Commit 7685fa4

Browse files
committed
feat: simplify ABV display and restore style navigation
Changes: 1. Simplified ABV display from "4.4% ABV (Medium)" to just "4.4%" - Removed redundant "ABV" text - users understand % means ABV - Removed subjective strength labels - users can decide for themselves 2. Restored clickable style navigation - Added tappable style chip below HeroInfoCard - Chip shows style name with chevron indicator - Tapping navigates to StyleScreen to view all drinks with that style - Includes accessibility semantics for screen readers All 542 tests passing.
1 parent 0bce56a commit 7685fa4

4 files changed

Lines changed: 64 additions & 5 deletions

File tree

lib/screens/drink_detail_screen.dart

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,11 @@ class _DrinkDetailScreenState extends State<DrinkDetailScreen> {
9292
SliverToBoxAdapter(
9393
child: _buildHeroCard(context, drink, theme),
9494
),
95+
// Style chip for navigation
96+
if (drink.style != null)
97+
SliverToBoxAdapter(
98+
child: _buildStyleChip(context, drink),
99+
),
95100
// Description
96101
if (drink.notes != null && drink.notes!.isNotEmpty)
97102
SliverToBoxAdapter(
@@ -167,15 +172,14 @@ class _DrinkDetailScreenState extends State<DrinkDetailScreen> {
167172
}
168173

169174
Widget _buildHeroCard(BuildContext context, Drink drink, ThemeData theme) {
170-
final strengthLabel = ABVStrengthHelper.getABVStrengthLabel(drink.abv);
171175
final isSoldOut = drink.availabilityStatus == AvailabilityStatus.out;
172176

173177
return HeroInfoCard(
174178
rows: [
175179
// Style, dispense, ABV
176180
HeroInfoRow(
177181
icon: Icons.local_drink,
178-
text: '${drink.style ?? drink.category} · ${StringFormattingHelper.capitalizeFirst(drink.dispense)} · ${drink.abv.toStringAsFixed(1)}% ABV ($strengthLabel)',
182+
text: '${drink.style ?? drink.category} · ${StringFormattingHelper.capitalizeFirst(drink.dispense)} · ${drink.abv.toStringAsFixed(1)}%',
179183
),
180184
// Availability
181185
if (drink.bar != null || isSoldOut)
@@ -192,6 +196,61 @@ class _DrinkDetailScreenState extends State<DrinkDetailScreen> {
192196
);
193197
}
194198

199+
Widget _buildStyleChip(BuildContext context, Drink drink) {
200+
final theme = Theme.of(context);
201+
202+
return Padding(
203+
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
204+
child: Semantics(
205+
label: 'View all ${drink.style} drinks',
206+
hint: 'Double tap to see all drinks with this style',
207+
button: true,
208+
child: InkWell(
209+
onTap: () => _navigateToStyleScreen(context, drink.style!),
210+
borderRadius: BorderRadius.circular(20),
211+
child: Container(
212+
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
213+
decoration: BoxDecoration(
214+
color: theme.colorScheme.secondaryContainer,
215+
borderRadius: BorderRadius.circular(20),
216+
border: Border.all(
217+
color: theme.colorScheme.secondary.withValues(alpha: 0.3),
218+
),
219+
),
220+
child: Row(
221+
mainAxisSize: MainAxisSize.min,
222+
children: [
223+
Icon(
224+
Icons.local_drink,
225+
size: 16,
226+
color: theme.colorScheme.onSecondaryContainer,
227+
),
228+
const SizedBox(width: 6),
229+
Text(
230+
drink.style!,
231+
style: theme.textTheme.bodyMedium?.copyWith(
232+
color: theme.colorScheme.onSecondaryContainer,
233+
fontWeight: FontWeight.w500,
234+
),
235+
),
236+
const SizedBox(width: 4),
237+
Icon(
238+
Icons.chevron_right,
239+
size: 16,
240+
color: theme.colorScheme.onSecondaryContainer,
241+
),
242+
],
243+
),
244+
),
245+
),
246+
),
247+
);
248+
}
249+
250+
void _navigateToStyleScreen(BuildContext context, String style) {
251+
context.go(buildStylePath(widget.festivalId, style));
252+
}
253+
195254
Widget _buildDescription(BuildContext context, Drink drink, ThemeData theme) {
196255
return Column(
197256
crossAxisAlignment: CrossAxisAlignment.start,

test/drink_detail_screen_test.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ void main() {
120120
await tester.pumpAndSettle();
121121

122122
// New layout shows combined information in HeroInfoCard
123-
expect(find.textContaining('5.0% ABV'), findsOneWidget);
124-
expect(find.textContaining('IPA'), findsOneWidget);
123+
expect(find.textContaining('5.0%'), findsOneWidget);
124+
expect(find.textContaining('IPA'), findsWidgets); // Appears in HeroInfoCard and style chip
125125
expect(find.textContaining('Cask'), findsOneWidget);
126126
expect(find.textContaining('Available at Main Bar'), findsOneWidget);
127127
});
@@ -222,7 +222,7 @@ void main() {
222222
await tester.pumpAndSettle();
223223

224224
expect(find.text('Brewery'), findsOneWidget);
225-
expect(find.byIcon(Icons.chevron_right), findsOneWidget);
225+
expect(find.byIcon(Icons.chevron_right), findsNWidgets(2)); // Style chip + brewery card
226226
});
227227

228228
testWidgets('has share button in app bar',
874 Bytes
Loading
1.29 KB
Loading

0 commit comments

Comments
 (0)