@@ -259,7 +259,7 @@ class _AnimatedScaleOnTapState extends State<AnimatedScaleOnTap> {
259
259
}
260
260
}
261
261
262
- /// The rounded-rectangle shape and 1-pixel spacing for a run of [MenuButton ] s.
262
+ /// The rounded-rectangle shape and 1-pixel spacing for a run of [ZulipMenuItemButton ] s.
263
263
class MenuButtonsShape extends StatelessWidget {
264
264
const MenuButtonsShape ({
265
265
super .key,
@@ -277,21 +277,25 @@ class MenuButtonsShape extends StatelessWidget {
277
277
}
278
278
}
279
279
280
- /// The "menu button" component in Figma.
280
+ /// The "menu button" or "list button" component in Figma.
281
+ ///
282
+ /// Use [ZulipMenuItemButtonStyle] to choose between components.
281
283
///
282
284
/// Must have a [MenuButtonsShape] ancestor.
283
285
///
284
286
/// See Figma:
285
287
/// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6070-60681&m=dev
286
- class MenuButton extends StatelessWidget {
287
- const MenuButton ({
288
+ class ZulipMenuItemButton extends StatelessWidget {
289
+ const ZulipMenuItemButton ({
288
290
super .key,
291
+ this .style = ZulipMenuItemButtonStyle .menu,
289
292
required this .label,
290
293
required this .onPressed,
291
294
this .icon,
292
295
this .toggle,
293
296
});
294
297
298
+ final ZulipMenuItemButtonStyle style;
295
299
final String label;
296
300
final VoidCallback onPressed;
297
301
final IconData ? icon;
@@ -300,22 +304,63 @@ class MenuButton extends StatelessWidget {
300
304
///
301
305
/// See Figma:
302
306
/// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=6070-60682&m=dev
307
+ // TODO(design) Is the toggle option meant only for
308
+ // [ZulipMenuItemButtonStyle.menu]?
303
309
final Widget ? toggle;
304
310
305
- static double itemSpacing = 16 ;
311
+ double get itemSpacingAndEndPadding => switch (style) {
312
+ ZulipMenuItemButtonStyle .menu => 16 ,
313
+ ZulipMenuItemButtonStyle .list => 12 ,
314
+ };
306
315
307
316
static bool _debugCheckShapeAncestor (BuildContext context) {
308
317
final ancestor = context.findAncestorWidgetOfExactType <MenuButtonsShape >();
309
318
assert (() {
310
319
if (ancestor != null ) return true ;
311
320
throw FlutterError .fromParts ([
312
321
ErrorSummary ('No MenuButtonsShape ancestor found.' ),
313
- ErrorDescription ('MenuButton widgets require a MenuButtonsShape ancestor.' ),
322
+ ErrorDescription ('ZulipMenuItemButton widgets require a MenuButtonsShape ancestor.' ),
314
323
]);
315
324
}());
316
325
return true ;
317
326
}
318
327
328
+ WidgetStateColor _backgroundColor (DesignVariables designVariables) {
329
+ switch (style) {
330
+ case ZulipMenuItemButtonStyle .menu:
331
+ return WidgetStateColor .fromMap ({
332
+ WidgetState .pressed: designVariables.contextMenuItemBg.withFadedAlpha (0.20 ),
333
+ ~ WidgetState .pressed: designVariables.contextMenuItemBg.withFadedAlpha (0.12 ),
334
+ });
335
+ case ZulipMenuItemButtonStyle .list:
336
+ return WidgetStateColor .fromMap ({
337
+ WidgetState .pressed: designVariables.listMenuItemBg.withFadedAlpha (0.7 ),
338
+ ~ WidgetState .pressed: designVariables.listMenuItemBg.withFadedAlpha (0.35 ),
339
+ });
340
+ }
341
+ }
342
+
343
+ Color _labelColor (DesignVariables designVariables) {
344
+ return switch (style) {
345
+ ZulipMenuItemButtonStyle .menu => designVariables.contextMenuItemText,
346
+ ZulipMenuItemButtonStyle .list => designVariables.listMenuItemText,
347
+ };
348
+ }
349
+
350
+ double _labelWght () {
351
+ return switch (style) {
352
+ ZulipMenuItemButtonStyle .menu => 600 ,
353
+ ZulipMenuItemButtonStyle .list => 500 ,
354
+ };
355
+ }
356
+
357
+ Color _iconColor (DesignVariables designVariables) {
358
+ return switch (style) {
359
+ ZulipMenuItemButtonStyle .menu => designVariables.contextMenuItemIcon,
360
+ ZulipMenuItemButtonStyle .list => designVariables.listMenuItemIcon,
361
+ };
362
+ }
363
+
319
364
@override
320
365
Widget build (BuildContext context) {
321
366
_debugCheckShapeAncestor (context);
@@ -331,35 +376,48 @@ class MenuButton extends StatelessWidget {
331
376
// This Material widget gives us 12px padding before the icon --
332
377
// or more or less, depending on Theme.of(context).visualDensity,
333
378
// hence the `assert` above.
334
- padding: EdgeInsetsDirectional .only (start: itemSpacing - 12 ),
379
+ padding: EdgeInsetsDirectional .only (start: itemSpacingAndEndPadding - 12 ),
335
380
336
381
child: Row (
337
382
mainAxisSize: MainAxisSize .min,
338
383
crossAxisAlignment: CrossAxisAlignment .center,
339
- spacing: itemSpacing ,
384
+ spacing: itemSpacingAndEndPadding ,
340
385
children: [
341
386
if (toggle != null ) toggle! ,
342
- if (icon != null ) Icon (icon! , color: designVariables.contextMenuItemIcon ),
387
+ if (icon != null ) Icon (icon! , color: _iconColor ( designVariables) ),
343
388
]))
344
389
: null ,
345
390
style: MenuItemButton .styleFrom (
346
391
minimumSize: Size .fromHeight (48 ),
347
- padding: const EdgeInsets . symmetric (horizontal : 16 ),
348
- foregroundColor: designVariables.contextMenuItemText ,
392
+ padding: EdgeInsetsDirectional . only (start : 16 , end : itemSpacingAndEndPadding ),
393
+ foregroundColor: _labelColor ( designVariables) ,
349
394
splashFactory: NoSplash .splashFactory,
350
- ).copyWith (backgroundColor: WidgetStateColor .resolveWith ((states) =>
351
- designVariables.contextMenuItemBg.withFadedAlpha (
352
- states.contains (WidgetState .pressed) ? 0.20 : 0.12 ))),
395
+ ).copyWith (backgroundColor: _backgroundColor (designVariables)),
353
396
onPressed: onPressed,
354
397
child: Padding (
355
398
padding: const EdgeInsets .symmetric (vertical: 4 ),
399
+ // TODO sublabel, for [ZulipMenuItemButtonStyle.list]
356
400
child: Text (label,
357
401
style: const TextStyle (fontSize: 20 , height: 24 / 20 )
358
- .merge (weightVariableTextStyle (context, wght: 600 ))),
359
- ));
402
+ .merge (weightVariableTextStyle (context, wght: _labelWght ())))));
360
403
}
361
404
}
362
405
406
+ /// The style of a [ZulipMenuItemButton] .
407
+ enum ZulipMenuItemButtonStyle {
408
+ /// The purple "menu button" component in Figma, with 16px end padding.
409
+ ///
410
+ /// See Figma:
411
+ /// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=3302-20443&m=dev
412
+ menu,
413
+
414
+ /// The gray "list button" component in Figma, with 12px end padding.
415
+ ///
416
+ /// See Figma:
417
+ /// https://www.figma.com/design/1JTNtYo9memgW7vV6d0ygq/Zulip-Mobile?node-id=5000-52868&m=dev
418
+ list,
419
+ }
420
+
363
421
/// The "toggle" component in Figma.
364
422
///
365
423
/// See Figma:
0 commit comments