material_adaptive_sheets/README.md
2026-11-03 14:51:33 -05:00

103 lines
4.5 KiB
Markdown

Material sheets, menus and popovers that adapt to the window size. On narrow windows they show as bottom sheets, and on wide windows as dialogs, popovers and popup menus.
## Features
- `showAdaptiveSheet`: a dialog on desktop, or a bottom sheet on mobile
- `showAdaptivePopover`: a popover anchored to a widget or point on desktop, or a bottom sheet on mobile
- `showAdaptiveMenu`: a popup menu on desktop, or a bottom sheet of the same `PopupMenuEntry`s on mobile
- `AdaptiveMenuButton`: like `PopupMenuButton`, but shows a bottom sheet on mobile
- `SheetLayout`: a title, scrollable content and actions, laid out for both sheets and dialogs
- `AdaptiveBreakpoint`: configure the width where the desktop layout starts
## Screenshots
| | Mobile | Desktop |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Sheet | ![A bottom sheet asking to delete conversations](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/sheet_mobile.png) | ![A dialog asking to delete conversations](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/sheet_desktop.png) |
| Menu | ![A bottom sheet with menu items](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/menu_mobile.png) | ![A popup menu over the menu button](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/menu_desktop.png) |
| Popover | ![A bottom sheet with inbox details](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/popover_mobile.png) | ![A popover with inbox details below the info button](https://git.federated.nexus/Henry-Hiles/material_adaptive_sheets/raw/branch/main/assets/screenshots/popover_desktop.png) |
<!-- The screenshots are rendered by `test/screenshots_test.dart`. Regenerate them with `flutter test --update-goldens`. -->
## Getting started
Add the package to your project with `flutter pub add material_adaptive_sheets`.
## Usage
All of the `show` methods are extensions on `BuildContext`, and return the value the sheet was closed with.
### Sheets
```dart
final confirmed = await context.showAdaptiveSheet<bool>(
(context) => SheetLayout(
title: const Text("Delete message?"),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text("Cancel"),
),
FilledButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text("Delete"),
),
],
children: [const Text("This can't be undone.")],
),
);
```
### Menus
```dart
AdaptiveMenuButton<String>(
icon: const Icon(Icons.more_vert),
itemBuilder: (context) => const [
PopupMenuItem(value: "edit", child: Text("Edit")),
PopupMenuItem(value: "delete", child: Text("Delete")),
],
onSelected: (value) => print(value),
);
```
Or show a menu at a point, like where the user right clicked:
```dart
GestureDetector(
onSecondaryTapUp: (details) => context.showAdaptiveMenu(
items,
globalPosition: details.globalPosition,
),
child: child,
);
```
### Popovers
```dart
IconButton(
icon: const Icon(Icons.info),
onPressed: () => context.showAdaptivePopover(
(context) => const Padding(
padding: EdgeInsets.all(16),
child: Text("Some details"),
),
),
);
```
On desktop, the popover opens below the widget the context belongs to, or above it if there isn't room. Pass `anchor` to open it somewhere else, such as `context.globalRectAt(details.globalPosition)`.
### Breakpoint
By default, the desktop layout is used for windows wider than 650 logical pixels. To change this, wrap your app in an `AdaptiveBreakpoint`:
```dart
AdaptiveBreakpoint(
width: 800,
child: MaterialApp(...),
);
```
`context.isDesktop` is also exported, so the rest of your layout can use the same breakpoint.