diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb index 05598dab42..d9da48e56e 100644 --- a/assets/l10n/app_en.arb +++ b/assets/l10n/app_en.arb @@ -1231,6 +1231,18 @@ "@wildcardMentionTopicDescription": { "description": "Description for \"@topic\" wildcard-mention autocomplete options when writing a channel message." }, + "navBarFeedLabel": "Combined feed", + "@navBarFeedLabel": { + "description": "Label for the Feed button on the bottom navigation bar." + }, + "navBarDmLabel": "DMs", + "@navBarDmLabel": { + "description": "Label for the Direct Messages button on the bottom navigation bar." + }, + "navBarMenuLabel": "Menu", + "@navBarMenuLabel": { + "description": "Label for the Menu button on the bottom navigation bar." + }, "messageIsEditedLabel": "EDITED", "@messageIsEditedLabel": { "description": "Label for an edited message. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.)" diff --git a/lib/generated/l10n/zulip_localizations.dart b/lib/generated/l10n/zulip_localizations.dart index 984721ff13..0b9b112f89 100644 --- a/lib/generated/l10n/zulip_localizations.dart +++ b/lib/generated/l10n/zulip_localizations.dart @@ -1791,6 +1791,24 @@ abstract class ZulipLocalizations { /// **'Notify topic'** String get wildcardMentionTopicDescription; + /// Label for the Feed button on the bottom navigation bar. + /// + /// In en, this message translates to: + /// **'Combined feed'** + String get navBarFeedLabel; + + /// Label for the Direct Messages button on the bottom navigation bar. + /// + /// In en, this message translates to: + /// **'DMs'** + String get navBarDmLabel; + + /// Label for the Menu button on the bottom navigation bar. + /// + /// In en, this message translates to: + /// **'Menu'** + String get navBarMenuLabel; + /// Label for an edited message. (Use ALL CAPS for cased alphabets: Latin, Greek, Cyrillic, etc.) /// /// In en, this message translates to: diff --git a/lib/generated/l10n/zulip_localizations_ar.dart b/lib/generated/l10n/zulip_localizations_ar.dart index 323068f599..178b771564 100644 --- a/lib/generated/l10n/zulip_localizations_ar.dart +++ b/lib/generated/l10n/zulip_localizations_ar.dart @@ -1027,6 +1027,15 @@ class ZulipLocalizationsAr extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'إخطار الموضوع'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'EDITED'; diff --git a/lib/generated/l10n/zulip_localizations_de.dart b/lib/generated/l10n/zulip_localizations_de.dart index d693740f43..3edfa6b76e 100644 --- a/lib/generated/l10n/zulip_localizations_de.dart +++ b/lib/generated/l10n/zulip_localizations_de.dart @@ -1050,6 +1050,15 @@ class ZulipLocalizationsDe extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Thema benachrichtigen'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'BEARBEITET'; diff --git a/lib/generated/l10n/zulip_localizations_en.dart b/lib/generated/l10n/zulip_localizations_en.dart index 7079d98e3c..540aa459a2 100644 --- a/lib/generated/l10n/zulip_localizations_en.dart +++ b/lib/generated/l10n/zulip_localizations_en.dart @@ -1027,6 +1027,15 @@ class ZulipLocalizationsEn extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notify topic'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'EDITED'; diff --git a/lib/generated/l10n/zulip_localizations_fr.dart b/lib/generated/l10n/zulip_localizations_fr.dart index d06ba5e034..3c72cd0675 100644 --- a/lib/generated/l10n/zulip_localizations_fr.dart +++ b/lib/generated/l10n/zulip_localizations_fr.dart @@ -1041,6 +1041,15 @@ class ZulipLocalizationsFr extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notify topic'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'EDITED'; diff --git a/lib/generated/l10n/zulip_localizations_it.dart b/lib/generated/l10n/zulip_localizations_it.dart index cccd1dc8b1..8dc5222d5a 100644 --- a/lib/generated/l10n/zulip_localizations_it.dart +++ b/lib/generated/l10n/zulip_localizations_it.dart @@ -1042,6 +1042,15 @@ class ZulipLocalizationsIt extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notifica argomento'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'MODIFICATO'; diff --git a/lib/generated/l10n/zulip_localizations_ja.dart b/lib/generated/l10n/zulip_localizations_ja.dart index 5f6fa404d4..f8862a59dd 100644 --- a/lib/generated/l10n/zulip_localizations_ja.dart +++ b/lib/generated/l10n/zulip_localizations_ja.dart @@ -1006,6 +1006,15 @@ class ZulipLocalizationsJa extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'トピック参加者に通知'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => '編集済み'; diff --git a/lib/generated/l10n/zulip_localizations_nb.dart b/lib/generated/l10n/zulip_localizations_nb.dart index 168bfc2757..04f33ad2fd 100644 --- a/lib/generated/l10n/zulip_localizations_nb.dart +++ b/lib/generated/l10n/zulip_localizations_nb.dart @@ -1027,6 +1027,15 @@ class ZulipLocalizationsNb extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notify topic'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'EDITED'; diff --git a/lib/generated/l10n/zulip_localizations_pl.dart b/lib/generated/l10n/zulip_localizations_pl.dart index 98d6b1de53..1c99d69bc7 100644 --- a/lib/generated/l10n/zulip_localizations_pl.dart +++ b/lib/generated/l10n/zulip_localizations_pl.dart @@ -1042,6 +1042,15 @@ class ZulipLocalizationsPl extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Powiadom w wątku'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'ZMIENIONO'; diff --git a/lib/generated/l10n/zulip_localizations_ru.dart b/lib/generated/l10n/zulip_localizations_ru.dart index 7effd9fa73..5a0f01c72c 100644 --- a/lib/generated/l10n/zulip_localizations_ru.dart +++ b/lib/generated/l10n/zulip_localizations_ru.dart @@ -1054,6 +1054,15 @@ class ZulipLocalizationsRu extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Оповестить тему'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'ИЗМЕНЕНО'; diff --git a/lib/generated/l10n/zulip_localizations_sk.dart b/lib/generated/l10n/zulip_localizations_sk.dart index 5cbbfcc1e4..2b16f98564 100644 --- a/lib/generated/l10n/zulip_localizations_sk.dart +++ b/lib/generated/l10n/zulip_localizations_sk.dart @@ -1029,6 +1029,15 @@ class ZulipLocalizationsSk extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notify topic'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'UPRAVENÉ'; diff --git a/lib/generated/l10n/zulip_localizations_sl.dart b/lib/generated/l10n/zulip_localizations_sl.dart index 8bfc8810cb..93fe537382 100644 --- a/lib/generated/l10n/zulip_localizations_sl.dart +++ b/lib/generated/l10n/zulip_localizations_sl.dart @@ -1064,6 +1064,15 @@ class ZulipLocalizationsSl extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Obvesti udeležence teme'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'UREJENO'; diff --git a/lib/generated/l10n/zulip_localizations_uk.dart b/lib/generated/l10n/zulip_localizations_uk.dart index f5b955fb55..69546a23d9 100644 --- a/lib/generated/l10n/zulip_localizations_uk.dart +++ b/lib/generated/l10n/zulip_localizations_uk.dart @@ -1043,6 +1043,15 @@ class ZulipLocalizationsUk extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Повідомити канал'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'РЕДАГОВАНО'; diff --git a/lib/generated/l10n/zulip_localizations_zh.dart b/lib/generated/l10n/zulip_localizations_zh.dart index 092bcd38e2..39b5d60b79 100644 --- a/lib/generated/l10n/zulip_localizations_zh.dart +++ b/lib/generated/l10n/zulip_localizations_zh.dart @@ -1027,6 +1027,15 @@ class ZulipLocalizationsZh extends ZulipLocalizations { @override String get wildcardMentionTopicDescription => 'Notify topic'; + @override + String get navBarFeedLabel => 'Combined feed'; + + @override + String get navBarDmLabel => 'DMs'; + + @override + String get navBarMenuLabel => 'Menu'; + @override String get messageIsEditedLabel => 'EDITED'; diff --git a/lib/widgets/home.dart b/lib/widgets/home.dart index 62c09c0857..1db8914646 100644 --- a/lib/widgets/home.dart +++ b/lib/widgets/home.dart @@ -86,6 +86,8 @@ class _HomePageState extends State { @override Widget build(BuildContext context) { + final zulipLocalizations = ZulipLocalizations.of(context); + const pageBodies = [ (_HomePageTab.inbox, InboxPageBody()), (_HomePageTab.channels, SubscriptionListPageBody()), @@ -93,28 +95,34 @@ class _HomePageState extends State { (_HomePageTab.directMessages, RecentDmConversationsPageBody()), ]; - _NavigationBarButton button(_HomePageTab tab, IconData icon) { + _NavigationBarButton button(_HomePageTab tab, IconData icon, String label) { return _NavigationBarButton(icon: icon, selected: _tab.value == tab, onPressed: () { _tab.value = tab; - }); + }, + label: label); } // TODO(a11y): add tooltips for these buttons final navigationBarButtons = [ - button(_HomePageTab.inbox, ZulipIcons.inbox), + button(_HomePageTab.inbox, ZulipIcons.inbox, + zulipLocalizations.inboxPageTitle), _NavigationBarButton( icon: ZulipIcons.message_feed, selected: false, onPressed: () => Navigator.push(context, MessageListPage.buildRoute(context: context, - narrow: const CombinedFeedNarrow()))), - button(_HomePageTab.channels, ZulipIcons.hash_italic), + narrow: const CombinedFeedNarrow())), + label: zulipLocalizations.navBarFeedLabel), + button(_HomePageTab.channels, ZulipIcons.hash_italic, + zulipLocalizations.channelsPageTitle), // TODO(#1094): Users - button(_HomePageTab.directMessages, ZulipIcons.two_person), + button(_HomePageTab.directMessages, ZulipIcons.two_person, + zulipLocalizations.navBarDmLabel), _NavigationBarButton( icon: ZulipIcons.menu, selected: false, - onPressed: () => _showMainMenu(context, tabNotifier: _tab)), + onPressed: () => _showMainMenu(context, tabNotifier: _tab), + label: zulipLocalizations.navBarMenuLabel), ]; final designVariables = DesignVariables.of(context); @@ -124,17 +132,19 @@ class _HomePageState extends State { body: Stack( children: [ for (final (tab, body) in pageBodies) - // TODO(#535): Decide if we find it helpful to use something like - // [SemanticsProperties.namesRoute] to structure this UI better - // for screen-reader software. - Offstage(offstage: tab != _tab.value, child: body), + Offstage( + offstage: tab != _tab.value, + child: Semantics( + namesRoute: true, + child: body)) ]), bottomNavigationBar: DecoratedBox( decoration: BoxDecoration( border: Border(top: BorderSide(color: designVariables.borderBar)), color: designVariables.bgBotBar), child: SafeArea( - child: SizedBox(height: 48, + child: SizedBox( + height: 62, child: Center( child: ConstrainedBox( // TODO(design): determine a suitable max width for bottom nav bar @@ -231,35 +241,46 @@ class _NavigationBarButton extends StatelessWidget { required this.icon, required this.selected, required this.onPressed, + required this.label, }); final IconData icon; final bool selected; final void Function() onPressed; + final String label; @override Widget build(BuildContext context) { final designVariables = DesignVariables.of(context); - final iconColor = WidgetStateColor.fromMap({ - WidgetState.pressed: designVariables.iconSelected, - ~WidgetState.pressed: selected ? designVariables.iconSelected - : designVariables.icon, - }); + final color = selected ? designVariables.iconSelected : designVariables.icon; return AnimatedScaleOnTap( scaleEnd: 0.875, duration: const Duration(milliseconds: 100), - child: IconButton( - icon: Icon(icon, size: 24), - onPressed: onPressed, - style: IconButton.styleFrom( - // TODO(#417): Disable splash effects for all buttons globally. - splashFactory: NoSplash.splashFactory, - highlightColor: designVariables.navigationButtonBg, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(4))), - ).copyWith(foregroundColor: iconColor))); + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: onPressed, + child: Column( + children: [ + SizedBox( + height: 34, + child: Center( + child: Icon(icon, size: 24, color: color,)), + ), + Expanded( + child: Text( + label, + style: TextStyle( + fontSize: 12, + color: color, + height: 1.0,), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis), + ) + ]), + )); } } diff --git a/test/widgets/home_test.dart b/test/widgets/home_test.dart index 1ee0a0ae8e..50bebcd39d 100644 --- a/test/widgets/home_test.dart +++ b/test/widgets/home_test.dart @@ -117,18 +117,27 @@ void main () { check(find.descendant( of: find.byType(ZulipAppBar), matching: find.text('Inbox'))).findsOne(); + check(find.descendant( + of: find.byType(ZulipAppBar), + matching: find.bySemanticsLabel(RegExp("Inbox")))).findsOne(); await tester.tap(find.byIcon(ZulipIcons.hash_italic)); await tester.pump(); check(find.descendant( of: find.byType(ZulipAppBar), matching: find.text('Channels'))).findsOne(); + check(find.descendant( + of: find.byType(ZulipAppBar), + matching: find.bySemanticsLabel(RegExp("Channels")))).findsOne(); await tester.tap(find.byIcon(ZulipIcons.two_person)); await tester.pump(); check(find.descendant( of: find.byType(ZulipAppBar), matching: find.text('Direct messages'))).findsOne(); + check(find.descendant( + of: find.byType(ZulipAppBar), + matching: find.bySemanticsLabel(RegExp("Direct messages")))).findsOne(); }); testWidgets('combined feed', (tester) async {