From add2a4d718890137b527d5aa1bc3327d2adf51d9 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 25 May 2024 09:41:04 +0200 Subject: [PATCH 1/2] KP page accessibility improvements --- .../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..65776f0d337 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 From 64ae73ca920ed0d4734f7e1670eaac6575121272 Mon Sep 17 00:00:00 2001 From: Edouard Marquez Date: Sat, 25 May 2024 09:49:29 +0200 Subject: [PATCH 2/2] ScoreCardType as a public enum --- .../smooth_app/lib/cards/data_cards/score_card.dart | 12 ++++++------ 1 file changed, 6 insertions(+), 6 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 65776f0d337..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,7 @@ class ScoreCard extends StatelessWidget { required Attribute attribute, required this.isClickable, this.margin, - }) : type = _ScoreCardType.attribute, + }) : type = ScoreCardType.attribute, iconUrl = attribute.iconUrl, description = attribute.descriptionShort ?? attribute.description ?? '', cardEvaluation = getCardEvaluationFromAttribute(attribute); @@ -57,7 +57,7 @@ class ScoreCard extends StatelessWidget { required TitleElement titleElement, required this.isClickable, this.margin, - }) : type = _ScoreCardType.title, + }) : type = ScoreCardType.title, iconUrl = titleElement.iconUrl, description = titleElement.title, cardEvaluation = @@ -68,7 +68,7 @@ class ScoreCard extends StatelessWidget { final CardEvaluation cardEvaluation; final bool isClickable; final EdgeInsetsGeometry? margin; - final _ScoreCardType type; + final ScoreCardType type; @override Widget build(BuildContext context) { @@ -88,7 +88,7 @@ class ScoreCard extends StatelessWidget { return Semantics( value: _generateSemanticsValue(context), excludeSemantics: true, - header: type == _ScoreCardType.title, + header: type == ScoreCardType.title, button: isClickable, child: Padding( padding: margin ?? const EdgeInsets.symmetric(vertical: SMALL_SPACE), @@ -128,7 +128,7 @@ class ScoreCard extends StatelessWidget { } String _generateSemanticsValue(BuildContext context) { - if (type == _ScoreCardType.title) { + if (type == ScoreCardType.title) { return description; } @@ -142,7 +142,7 @@ class ScoreCard extends StatelessWidget { } } -enum _ScoreCardType { +enum ScoreCardType { title, attribute, }