Skip to content

Commit

Permalink
Accessibility improvements for the list of prices (#5413)
Browse files Browse the repository at this point in the history
  • Loading branch information
g123k committed Jun 20, 2024
1 parent 7ee3a26 commit da76dd2
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 113 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,21 @@ class SmoothBackButton extends StatelessWidget {
final Color? iconColor;

@override
Widget build(BuildContext context) => Material(
type: MaterialType.transparency,
Widget build(BuildContext context) {
final MaterialLocalizations localizations =
MaterialLocalizations.of(context);

return Material(
type: MaterialType.transparency,
child: Semantics(
value: localizations.backButtonTooltip,
button: true,
excludeSemantics: true,
child: InkWell(
onTap: onPressed ?? () => Navigator.maybePop(context),
customBorder: const CircleBorder(),
child: Tooltip(
message: MaterialLocalizations.of(context).backButtonTooltip,
message: localizations.backButtonTooltip,
child: Padding(
padding: _iconPadding,
child: Icon(
Expand All @@ -36,7 +44,9 @@ class SmoothBackButton extends StatelessWidget {
),
),
),
);
),
);
}

/// The iOS/macOS icon requires a little padding to be well-centered
EdgeInsetsGeometry get _iconPadding {
Expand Down
43 changes: 43 additions & 0 deletions packages/smooth_app/lib/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1765,6 +1765,18 @@
},
"prices_barcode_reader_action": "Barcode reader",
"prices_view_prices": "View the prices",
"prices_product_accessibility_summary": "{count,plural, =1{1 price} other{{count} prices}} for {product}",
"@prices_product_accessibility_summary": {
"description": "A card summarizing the number of prices for a product",
"placeholders": {
"count": {
"type": "int"
},
"product": {
"type": "String"
}
}
},
"prices_list_length_one_page": "{count,plural, =0{No price yet} =1{Only one price} other{All {count} prices}}",
"@prices_list_length_one_page": {
"description": "Number of prices for one-page result",
Expand All @@ -1786,6 +1798,37 @@
}
}
},
"prices_entry_accessibility_label": "Price: {price} / Store: \"{location}\" / Published on {date} by \"{user}\"",
"@prices_entry_accessibility_label": {
"description": "Accessibility label for a price entry",
"placeholders": {
"price": {
"type": "String"
},
"location": {
"type": "String"
},
"date": {
"type": "String"
},
"user": {
"type": "String"
}
}
},
"prices_open_user_proofs": "Open proofs of \"{user}\"",
"@prices_open_user_proofs": {
"description": "Button to open the proofs of a user",
"placeholders": {
"user": {
"type": "String"
}
}
},
"prices_open_proof": "Open price proof",
"@prices_open_proof": {
"description": "Button to open a proof"
},
"prices_proofs_list_length_one_page": "{count,plural, =0{No proof yet} =1{Only one proof} other{All {count} proofs}}",
"@prices_proofs_list_length_one_page": {
"description": "Number of proofs for one-page result",
Expand Down
37 changes: 27 additions & 10 deletions packages/smooth_app/lib/pages/prices/price_button.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,52 @@ class PriceButton extends StatelessWidget {
this.title,
this.iconData,
this.buttonStyle,
this.tooltip,
required this.onPressed,
});

final String? title;
final IconData? iconData;
final ButtonStyle? buttonStyle;
final VoidCallback? onPressed;
final String? tooltip;

@override
Widget build(BuildContext context) {
final Widget widget;

if (iconData == null) {
return ElevatedButton(
widget = ElevatedButton(
onPressed: onPressed,
style: buttonStyle,
child: Text(title!),
);
}
if (title == null) {
return ElevatedButton(
} else if (title == null) {
widget = ElevatedButton(
onPressed: onPressed,
style: buttonStyle,
child: Icon(iconData),
);
} else {
widget = ElevatedButton.icon(
onPressed: onPressed,
icon: Icon(iconData),
label: Text(title!),
style: buttonStyle,
);
}

if (tooltip?.isNotEmpty == true) {
return Semantics(
value: tooltip,
button: true,
excludeSemantics: true,
child: Tooltip(
message: tooltip,
child: widget,
),
);
}
return ElevatedButton.icon(
onPressed: onPressed,
icon: Icon(iconData),
label: Text(title!),
style: buttonStyle,
);
return widget;
}
}
100 changes: 57 additions & 43 deletions packages/smooth_app/lib/pages/prices/price_data_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -62,53 +62,67 @@ class PriceDataWidget extends StatelessWidget {
final String? pricePerKg = getPricePerKg();
final String? notDiscountedPrice = getNotDiscountedPrice();

return Wrap(
alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: MEDIUM_SPACE,
children: <Widget>[
Text(
'${currencyFormat.format(price.price)}'
' ${pricePerKg == null ? '' : ' ($pricePerKg)'}',
),
Text(dateFormat.format(price.date)),
if (notDiscountedPrice != null) Text('($notDiscountedPrice)'),
if (locationTitle != null)
// TODO(monsieurtanuki): open a still-to-be-done "price x location" page
PriceButton(
title: locationTitle,
iconData: Icons.location_on_outlined,
onPressed: () {},
),
if (model.displayOwner) PriceUserButton(price.owner),
Tooltip(
message: '${dateFormat.format(price.created)}'
' '
'${timeFormat.format(price.created)}',
child: PriceButton(
// TODO(monsieurtanuki): misleading "active" button
onPressed: () {},
iconData: Icons.history,
title: ProductQueryPageHelper.getDurationStringFromTimestamp(
price.created.millisecondsSinceEpoch,
context,
compact: true,
final String priceLabel = '${currencyFormat.format(price.price)}'
' ${pricePerKg == null ? '' : ' ($pricePerKg)'}';
return Semantics(
container: true,
explicitChildNodes: false,
label: appLocalizations.prices_entry_accessibility_label(
priceLabel,
locationTitle ?? '-',
dateFormat.format(price.date),
price.owner,
),
child: Wrap(
alignment: WrapAlignment.start,
crossAxisAlignment: WrapCrossAlignment.center,
spacing: MEDIUM_SPACE,
children: <Widget>[
ExcludeSemantics(child: Text(priceLabel)),
ExcludeSemantics(child: Text(dateFormat.format(price.date))),
if (notDiscountedPrice != null) Text('($notDiscountedPrice)'),
if (locationTitle != null)
// TODO(monsieurtanuki): open a still-to-be-done "price x location" page
ExcludeSemantics(
child: PriceButton(
title: locationTitle,
iconData: Icons.location_on_outlined,
onPressed: () {},
),
),
),
),
if (price.proof?.filePath != null)
PriceButton(
iconData: Icons.image,
onPressed: () async => Navigator.push<void>(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => PriceProofPage(
price.proof!,
if (model.displayOwner) PriceUserButton(price.owner),
ExcludeSemantics(
child: Tooltip(
message: '${dateFormat.format(price.created)}'
' '
'${timeFormat.format(price.created)}',
child: PriceButton(
// TODO(monsieurtanuki): misleading "active" button
onPressed: () {},
iconData: Icons.history,
title: ProductQueryPageHelper.getDurationStringFromTimestamp(
price.created.millisecondsSinceEpoch,
context,
compact: true,
),
),
), // PriceProofPage
),
),
],
if (price.proof?.filePath != null)
PriceButton(
iconData: Icons.image,
tooltip: appLocalizations.prices_open_proof,
onPressed: () async => Navigator.push<void>(
context,
MaterialPageRoute<void>(
builder: (BuildContext context) => PriceProofPage(
price.proof!,
),
),
), // PriceProofPage
),
],
),
);
}

Expand Down
Loading

0 comments on commit da76dd2

Please sign in to comment.