Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 39 additions & 27 deletions lib/widgets/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,13 @@ class _MainMenuHeaderState extends State<_MainMenuHeader> {
}
}

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

String label(ZulipLocalizations zulipLocalizations);

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

// Make [TextButton] set 44 instead of 48 for the height.
final visualDensity = VisualDensity(vertical: -1);
// A value that [TextButton] adds to some of its layout parameters;
// we can cancel out those adjustments by subtracting it.
final densityVerticalAdjustment = visualDensity.baseSizeAdjustment.dy;

final borderSideSelected = BorderSide(width: 1,
strokeAlign: BorderSide.strokeAlignOutside,
color: designVariables.borderMenuButtonSelected);
final buttonStyle = TextButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 9, horizontal: 8),
// Make the button 44px instead of 48px tall, to match the Figma.
visualDensity: visualDensity,
padding: EdgeInsets.symmetric(
vertical: 10 - densityVerticalAdjustment, horizontal: 8),
foregroundColor: designVariables.labelMenuButton,
// This has a default behavior of affecting the background color of the
// button for states including "hovered", "focused" and "pressed".
Expand All @@ -554,26 +568,24 @@ abstract class _MenuButton extends StatelessWidget {
return AnimatedScaleOnTap(
duration: const Duration(milliseconds: 100),
scaleEnd: 0.95,
child: ConstrainedBox(
constraints: const BoxConstraints(minHeight: 44),
child: TextButton(
onPressed: () => _handlePress(context),
style: buttonStyle,
child: Row(spacing: 8, children: [
SizedBox.square(dimension: _iconSize,
child: buildLeading(context)),
Expanded(child: Text(label(zulipLocalizations),
// TODO(design): determine if we prefer to wrap
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 19, height: 26 / 19)
.merge(weightVariableTextStyle(context, wght: selected ? 600 : 400)))),
?trailing,
]))));
child: TextButton(
onPressed: () => _handlePress(context),
style: buttonStyle,
child: Row(spacing: 8, children: [
SizedBox.square(dimension: _iconSize,
child: buildLeading(context)),
Expanded(child: Text(label(zulipLocalizations),
// TODO(design): determine if we prefer to wrap
overflow: TextOverflow.ellipsis,
style: const TextStyle(fontSize: 19, height: 23 / 19)
.merge(weightVariableTextStyle(context, wght: selected ? 600 : 400)))),
?trailing,
])));
}
}

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

final ValueNotifier<_HomePageTab> tabNotifier;
Expand All @@ -589,7 +601,7 @@ abstract class _NavigationBarMenuButton extends _MenuButton {
}
}

class _SearchButton extends _MenuButton {
class _SearchButton extends MenuButton {
const _SearchButton();

@override
Expand Down Expand Up @@ -634,7 +646,7 @@ class _InboxButton extends _NavigationBarMenuButton {
_HomePageTab get navigationTarget => _HomePageTab.inbox;
}

class _MentionsButton extends _MenuButton {
class _MentionsButton extends MenuButton {
const _MentionsButton();

@override
Expand Down Expand Up @@ -664,7 +676,7 @@ class _MentionsButton extends _MenuButton {
}
}

class _StarredMessagesButton extends _MenuButton {
class _StarredMessagesButton extends MenuButton {
const _StarredMessagesButton();

@override
Expand All @@ -682,7 +694,7 @@ class _StarredMessagesButton extends _MenuButton {
}
}

class _CombinedFeedButton extends _MenuButton {
class _CombinedFeedButton extends MenuButton {
const _CombinedFeedButton();

@override
Expand Down Expand Up @@ -742,7 +754,7 @@ class _DirectMessagesButton extends _NavigationBarMenuButton {
_HomePageTab get navigationTarget => _HomePageTab.directMessages;
}

class _MyProfileButton extends _MenuButton {
class _MyProfileButton extends MenuButton {
const _MyProfileButton();

@override
Expand All @@ -753,7 +765,7 @@ class _MyProfileButton extends _MenuButton {
final store = PerAccountStoreWidget.of(context);
return Avatar(
userId: store.selfUserId,
size: _MenuButton._iconSize,
size: MenuButton._iconSize,
borderRadius: 4,
showPresence: false,
);
Expand All @@ -772,7 +784,7 @@ class _MyProfileButton extends _MenuButton {
}
}

class _SettingsButton extends _MenuButton {
class _SettingsButton extends MenuButton {
const _SettingsButton();

@override
Expand All @@ -789,7 +801,7 @@ class _SettingsButton extends _MenuButton {
}
}

class _AboutZulipButton extends _MenuButton {
class _AboutZulipButton extends MenuButton {
const _AboutZulipButton();

@override
Expand Down
19 changes: 19 additions & 0 deletions test/widgets/home_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,25 @@ void main () {
.isSameColorAs(designVariables.icon);
}

testWidgets('buttons are 44px tall', (tester) async {
prepareBoringImageHttpClient();
await prepare(tester);

await tapOpenMenuAndAwait(tester);
checkIconSelected(tester, inboxMenuIconFinder);
checkIconNotSelected(tester, channelsMenuIconFinder);

final inboxElement = tester.element(
find.ancestor(of: inboxMenuIconFinder, matching: find.bySubtype<MenuButton>()));
check((inboxElement.renderObject as RenderBox)).size.height.equals(44);

final channelsElement = tester.element(
find.ancestor(of: inboxMenuIconFinder, matching: find.bySubtype<MenuButton>()));
check((channelsElement.renderObject as RenderBox)).size.height.equals(44);

debugNetworkImageHttpClientProvider = null;
});

testWidgets('navigation states reflect on navigation bar menu buttons', (tester) async {
prepareBoringImageHttpClient();
await prepare(tester);
Expand Down