initial commit

This commit is contained in:
Henry Hiles 2026-11-03 14:46:28 -05:00
commit a747bdbd27
Signed by: Henry-Hiles
SSH key fingerprint: SHA256:VKQUdS31Q90KvX7EkKMHMBpUspcmItAh86a+v7PGiIs

103
README.md Normal file
View file

@ -0,0 +1,103 @@
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.