From 44e47749367d74b7b9cf19a795a848f6e9471b88 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 25 May 2024 17:15:03 +0200 Subject: [PATCH] feat: Knowledge Panel details page accessibility improvements (#5290) * KP page accessibility improvements * ScoreCardType as a public enum --- .../lib/cards/data_cards/score_card.dart | 19 ++++++++++-- .../knowledge_panel_group_card.dart | 11 ++++--- .../knowledge_panel_page.dart | 31 +++++++++++++++++-- .../knowledge_panel_text_card.dart | 8 +++-- packages/smooth_app/lib/l10n/app_en.arb | 21 +++++++++++++ 5 files changed, 77 insertions(+), 13 deletions(-) diff --git a/packages/smooth_app/lib/cards/data_cards/score_card.dart b/packages/smooth_app/lib/cards/data_cards/score_card.dart index 17ca032141b..e45143d3bda 100644 --- a/packages/smooth_app/lib/cards/data_cards/score_card.dart +++ b/packages/smooth_app/lib/cards/data_cards/score_card.dart @@ -48,7 +48,8 @@ class ScoreCard extends StatelessWidget { required Attribute attribute, required this.isClickable, this.margin, - }) : iconUrl = attribute.iconUrl, + }) : type = ScoreCardType.attribute, + iconUrl = attribute.iconUrl, description = attribute.descriptionShort ?? attribute.description ?? '', cardEvaluation = getCardEvaluationFromAttribute(attribute); @@ -56,7 +57,8 @@ class ScoreCard extends StatelessWidget { required TitleElement titleElement, required this.isClickable, this.margin, - }) : iconUrl = titleElement.iconUrl, + }) : type = ScoreCardType.title, + iconUrl = titleElement.iconUrl, description = titleElement.title, cardEvaluation = getCardEvaluationFromKnowledgePanelTitleElement(titleElement); @@ -66,6 +68,7 @@ class ScoreCard extends StatelessWidget { final CardEvaluation cardEvaluation; final bool isClickable; final EdgeInsetsGeometry? margin; + final ScoreCardType type; @override Widget build(BuildContext context) { @@ -85,7 +88,8 @@ class ScoreCard extends StatelessWidget { return Semantics( value: _generateSemanticsValue(context), excludeSemantics: true, - button: true, + header: type == ScoreCardType.title, + button: isClickable, child: Padding( padding: margin ?? const EdgeInsets.symmetric(vertical: SMALL_SPACE), child: Ink( @@ -124,6 +128,10 @@ class ScoreCard extends StatelessWidget { } String _generateSemanticsValue(BuildContext context) { + if (type == ScoreCardType.title) { + return description; + } + final String? iconLabel = SvgCache.getSemanticsLabel(context, iconUrl!); if (iconLabel == null) { @@ -133,3 +141,8 @@ class ScoreCard extends StatelessWidget { } } } + +enum ScoreCardType { + title, + attribute, +} diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart index 0ac2b7f6603..6c9ef63db4f 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_group_card.dart @@ -28,10 +28,13 @@ class KnowledgePanelGroupCard extends StatelessWidget { if (groupElement.title != null && groupElement.title!.isNotEmpty) Padding( padding: const EdgeInsetsDirectional.only(top: LARGE_SPACE), - child: Text( - groupElement.title!, - style: - themeData.textTheme.titleSmall!.apply(color: Colors.grey), + child: Semantics( + explicitChildNodes: true, + child: Text( + groupElement.title!, + style: + themeData.textTheme.titleSmall!.apply(color: Colors.grey), + ), ), ), for (final String panelId in groupElement.panelIds) diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart index 3d0ead01919..4d629568009 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_page.dart @@ -1,5 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:matomo_tracker/matomo_tracker.dart'; import 'package:openfoodfacts/openfoodfacts.dart'; import 'package:provider/provider.dart'; @@ -50,13 +51,19 @@ class _KnowledgePanelPageState extends State @override Widget build(BuildContext context) { + final AppLocalizations appLocalizations = AppLocalizations.of(context); + final String title = _getTitle(); + context.watch(); refreshUpToDate(); return SmoothScaffold( appBar: SmoothAppBar( - title: Text( - _getTitle(), - maxLines: 2, + title: Semantics( + label: _getTitleForAccessibility(appLocalizations, title), + child: Text( + title, + maxLines: 2, + ), ), ), body: RefreshIndicator( @@ -126,6 +133,24 @@ class _KnowledgePanelPageState extends State return ''; } + String _getTitleForAccessibility( + AppLocalizations appLocalizations, + String title, + ) { + final String productName = upToDateProduct.productName ?? + upToDateProduct.abbreviatedName ?? + upToDateProduct.genericName ?? + ''; + if (title.isEmpty) { + return appLocalizations.knowledge_panel_page_title_no_title(productName); + } else { + return appLocalizations.knowledge_panel_page_title( + title, + productName, + ); + } + } + @override void debugFillProperties(DiagnosticPropertiesBuilder properties) { super.debugFillProperties(properties); diff --git a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_text_card.dart b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_text_card.dart index 1d390fdd824..fb09b1747d5 100644 --- a/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_text_card.dart +++ b/packages/smooth_app/lib/knowledge_panel/knowledge_panels/knowledge_panel_text_card.dart @@ -18,9 +18,11 @@ class KnowledgePanelTextCard extends StatelessWidget { @override Widget build(BuildContext context) { - final Widget text = SmoothHtmlWidget( - textElement.html, - textStyle: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + final Widget text = MergeSemantics( + child: SmoothHtmlWidget( + textElement.html, + textStyle: WellSpacedTextHelper.TEXT_STYLE_WITH_WELL_SPACED, + ), ); if (!_hasSource) { diff --git a/packages/smooth_app/lib/l10n/app_en.arb b/packages/smooth_app/lib/l10n/app_en.arb index 99e024d0b15..89032527a79 100644 --- a/packages/smooth_app/lib/l10n/app_en.arb +++ b/packages/smooth_app/lib/l10n/app_en.arb @@ -2572,5 +2572,26 @@ "link_cant_be_opened": "This link can't be opened on your device. Please check that you have a browser installed.", "@link_cant_be_opened": { "description": "An error may happen if the device doesn't have a browser installed." + }, + "knowledge_panel_page_title_no_title": "Details for {productName}", + "@knowledge_panel_page_title_no_title": { + "description": "The title of the page when we click on an item in the product page and this page is unnamed", + "placeholders": { + "productName": { + "type": "String" + } + } + }, + "knowledge_panel_page_title": "Details for {pageName} with {productName}", + "@knowledge_panel_page_title": { + "description": "The title of the page when we click on an item in the product page", + "placeholders": { + "pageName": { + "type": "String" + }, + "productName": { + "type": "String" + } + } } } \ No newline at end of file