Skip to content

Commit ab36ab6

Browse files
committed
home: Tweak main-menu buttons to follow Figma
The buttons were 48px instead of 44px tall, and the label's line height was 26px instead of 23px.
1 parent 0347abe commit ab36ab6

File tree

2 files changed

+58
-27
lines changed

2 files changed

+58
-27
lines changed

lib/widgets/home.dart

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,13 @@ class _MainMenuHeaderState extends State<_MainMenuHeader> {
486486
}
487487
}
488488

489-
abstract class _MenuButton extends StatelessWidget {
490-
const _MenuButton();
489+
/// A button in the main menu.
490+
///
491+
/// See Figma:
492+
/// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=2037-243759&m=dev
493+
@visibleForTesting
494+
abstract class MenuButton extends StatelessWidget {
495+
const MenuButton({super.key});
491496

492497
String label(ZulipLocalizations zulipLocalizations);
493498

@@ -524,11 +529,20 @@ abstract class _MenuButton extends StatelessWidget {
524529
final designVariables = DesignVariables.of(context);
525530
final zulipLocalizations = ZulipLocalizations.of(context);
526531

532+
// Make [TextButton] set 44 instead of 48 for the height.
533+
final visualDensity = VisualDensity(vertical: -1);
534+
// A value that [TextButton] adds to some of its layout parameters;
535+
// we can cancel out those adjustments by subtracting it.
536+
final densityVerticalAdjustment = visualDensity.baseSizeAdjustment.dy;
537+
527538
final borderSideSelected = BorderSide(width: 1,
528539
strokeAlign: BorderSide.strokeAlignOutside,
529540
color: designVariables.borderMenuButtonSelected);
530541
final buttonStyle = TextButton.styleFrom(
531-
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 8),
542+
// Make the button 44px instead of 48px tall, to match the Figma.
543+
visualDensity: visualDensity,
544+
padding: EdgeInsets.symmetric(
545+
vertical: 10 - densityVerticalAdjustment, horizontal: 8),
532546
foregroundColor: designVariables.labelMenuButton,
533547
// This has a default behavior of affecting the background color of the
534548
// button for states including "hovered", "focused" and "pressed".
@@ -554,26 +568,24 @@ abstract class _MenuButton extends StatelessWidget {
554568
return AnimatedScaleOnTap(
555569
duration: const Duration(milliseconds: 100),
556570
scaleEnd: 0.95,
557-
child: ConstrainedBox(
558-
constraints: const BoxConstraints(minHeight: 44),
559-
child: TextButton(
560-
onPressed: () => _handlePress(context),
561-
style: buttonStyle,
562-
child: Row(spacing: 8, children: [
563-
SizedBox.square(dimension: _iconSize,
564-
child: buildLeading(context)),
565-
Expanded(child: Text(label(zulipLocalizations),
566-
// TODO(design): determine if we prefer to wrap
567-
overflow: TextOverflow.ellipsis,
568-
style: const TextStyle(fontSize: 19, height: 26 / 19)
569-
.merge(weightVariableTextStyle(context, wght: selected ? 600 : 400)))),
570-
?trailing,
571-
]))));
571+
child: TextButton(
572+
onPressed: () => _handlePress(context),
573+
style: buttonStyle,
574+
child: Row(spacing: 8, children: [
575+
SizedBox.square(dimension: _iconSize,
576+
child: buildLeading(context)),
577+
Expanded(child: Text(label(zulipLocalizations),
578+
// TODO(design): determine if we prefer to wrap
579+
overflow: TextOverflow.ellipsis,
580+
style: const TextStyle(fontSize: 19, height: 23 / 19)
581+
.merge(weightVariableTextStyle(context, wght: selected ? 600 : 400)))),
582+
?trailing,
583+
])));
572584
}
573585
}
574586

575587
/// A menu button controlling the selected [_HomePageTab] on the bottom nav bar.
576-
abstract class _NavigationBarMenuButton extends _MenuButton {
588+
abstract class _NavigationBarMenuButton extends MenuButton {
577589
const _NavigationBarMenuButton({required this.tabNotifier});
578590

579591
final ValueNotifier<_HomePageTab> tabNotifier;
@@ -589,7 +601,7 @@ abstract class _NavigationBarMenuButton extends _MenuButton {
589601
}
590602
}
591603

592-
class _SearchButton extends _MenuButton {
604+
class _SearchButton extends MenuButton {
593605
const _SearchButton();
594606

595607
@override
@@ -634,7 +646,7 @@ class _InboxButton extends _NavigationBarMenuButton {
634646
_HomePageTab get navigationTarget => _HomePageTab.inbox;
635647
}
636648

637-
class _MentionsButton extends _MenuButton {
649+
class _MentionsButton extends MenuButton {
638650
const _MentionsButton();
639651

640652
@override
@@ -664,7 +676,7 @@ class _MentionsButton extends _MenuButton {
664676
}
665677
}
666678

667-
class _StarredMessagesButton extends _MenuButton {
679+
class _StarredMessagesButton extends MenuButton {
668680
const _StarredMessagesButton();
669681

670682
@override
@@ -682,7 +694,7 @@ class _StarredMessagesButton extends _MenuButton {
682694
}
683695
}
684696

685-
class _CombinedFeedButton extends _MenuButton {
697+
class _CombinedFeedButton extends MenuButton {
686698
const _CombinedFeedButton();
687699

688700
@override
@@ -742,7 +754,7 @@ class _DirectMessagesButton extends _NavigationBarMenuButton {
742754
_HomePageTab get navigationTarget => _HomePageTab.directMessages;
743755
}
744756

745-
class _MyProfileButton extends _MenuButton {
757+
class _MyProfileButton extends MenuButton {
746758
const _MyProfileButton();
747759

748760
@override
@@ -753,7 +765,7 @@ class _MyProfileButton extends _MenuButton {
753765
final store = PerAccountStoreWidget.of(context);
754766
return Avatar(
755767
userId: store.selfUserId,
756-
size: _MenuButton._iconSize,
768+
size: MenuButton._iconSize,
757769
borderRadius: 4,
758770
showPresence: false,
759771
);
@@ -772,7 +784,7 @@ class _MyProfileButton extends _MenuButton {
772784
}
773785
}
774786

775-
class _SettingsButton extends _MenuButton {
787+
class _SettingsButton extends MenuButton {
776788
const _SettingsButton();
777789

778790
@override
@@ -789,7 +801,7 @@ class _SettingsButton extends _MenuButton {
789801
}
790802
}
791803

792-
class _AboutZulipButton extends _MenuButton {
804+
class _AboutZulipButton extends MenuButton {
793805
const _AboutZulipButton();
794806

795807
@override

test/widgets/home_test.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,25 @@ void main () {
256256
.isSameColorAs(designVariables.icon);
257257
}
258258

259+
testWidgets('buttons are 44px tall', (tester) async {
260+
prepareBoringImageHttpClient();
261+
await prepare(tester);
262+
263+
await tapOpenMenuAndAwait(tester);
264+
checkIconSelected(tester, inboxMenuIconFinder);
265+
checkIconNotSelected(tester, channelsMenuIconFinder);
266+
267+
final inboxElement = tester.element(
268+
find.ancestor(of: inboxMenuIconFinder, matching: find.bySubtype<MenuButton>()));
269+
check((inboxElement.renderObject as RenderBox)).size.height.equals(44);
270+
271+
final channelsElement = tester.element(
272+
find.ancestor(of: inboxMenuIconFinder, matching: find.bySubtype<MenuButton>()));
273+
check((channelsElement.renderObject as RenderBox)).size.height.equals(44);
274+
275+
debugNetworkImageHttpClientProvider = null;
276+
});
277+
259278
testWidgets('navigation states reflect on navigation bar menu buttons', (tester) async {
260279
prepareBoringImageHttpClient();
261280
await prepare(tester);

0 commit comments

Comments
 (0)