Watch
1
0
Fork
You've already forked nexus
0
forked from Nexus/nexus
nexus/lib/helpers/extensions/show_adaptive_menu.dart

52 lines
1.7 KiB
Dart

import "package:material_ui/material_ui.dart";
import "package:nexus/helpers/extensions/global_rect.dart";
import "package:nexus/helpers/extensions/is_desktop.dart";
extension ShowAdaptiveMenu on BuildContext {
/// Shows [items] in a popup menu on desktop, or a bottom sheet on mobile.
///
/// On desktop, the menu opens at [globalPosition] if given (e.g. where the
/// user right clicked), or over the widget this context belongs to.
Future<void> showAdaptiveMenu(
List<PopupMenuEntry> items, {
Offset? globalPosition,
}) async {
if (!isDesktop) {
await showModalBottomSheet(
context: this,
isScrollControlled: true,
showDragHandle: true,
builder: (context) => SafeArea(
child: SingleChildScrollView(
padding: const .only(bottom: 8),
// PopupMenuItems must be inside something with the menu role
child: Semantics(
role: .menu,
explicitChildNodes: true,
child: ListTileTheme.merge(
contentPadding: const .symmetric(horizontal: 24),
minTileHeight: 48,
titleTextStyle: Theme.of(context).textTheme.titleMedium,
child: Column(mainAxisSize: .min, children: items),
),
),
),
),
);
return;
}
final overlay = Overlay.of(this).context.findRenderObject() as RenderBox;
final anchor = switch (globalPosition) {
final position? => position & Size.zero,
null => globalRect,
};
await showMenu(
context: this,
constraints: .loose(.infinite),
position: .fromRect(anchor, Offset.zero & overlay.size),
items: items,
);
}
}