A customizable slide-up bottom sheet presentation for Flutter. Supports arbitrary height detents, a draggable grabber, an optional dimming scrim, keyboard avoidance, rotation, scroll coordination, and full layout-metric overrides — across iOS, Android, web, macOS, Windows, and Linux.
- Flutter 3.22+ / Dart 3.4+
Add to your pubspec.yaml:
dependencies:
bottom_shelfer:
git:
url: https://github.com/jonikay89/BottomShelfer_flutter.gitimport 'package:flutter/material.dart';
import 'package:bottom_shelfer/bottom_shelfer.dart';
final manager = BottomShelferPresentationManager(
detents: [
BottomShelferDetent.medium(context),
BottomShelferDetent.large(context),
],
selectedDetentIndex: 0,
);
showBottomShelfer(
context: context,
manager: manager,
builder: (context) => Container(
color: Colors.white,
child: const Center(child: Text('Hello sheet')),
),
);Predefined or custom-height snap points. The sheet always settles on one.
manager.copyWith(detents: [
BottomShelferDetent.small(context),
BottomShelferDetent.medium(context),
BottomShelferDetent.large(context),
]); // screen‑ratio
manager.copyWith(detents: const [BottomShelferDetent.custom(height: 320)]); // exact
manager.copyWith(detents: BottomShelferDetent.detentsForContentHeight(context, 420)); // auto‑sized
manager.copyWith(selectedDetentIndex: 1); // start on mediumVisual drag affordance at the top of the sheet. Size, offset, and corner radius
are all configurable via BottomShelferLayoutConfiguration.
final manager = BottomShelferPresentationManager(
layoutConfiguration: const BottomShelferLayoutConfiguration(
grabberPillSize: Size(56, 6),
grabberPillCornerRadius: 3,
),
);The pill animates on drag — scales up slightly and fades — then returns to
identity when released. Disable the pill entirely by setting its size to
Size.zero while keeping the drag gesture active.
Optional semi-transparent backdrop behind the sheet. Tap to dismiss (behavior
controlled by dismissOnHide).
final manager = BottomShelferPresentationManager(
isDimmingViewEnabled: false, // no scrim
dimmingColor: Colors.black.withOpacity(0.4), // custom color
);The sheet coordinates with embedded scrollables — when the scroll view is pinned to the top, a downward drag transfers control from the scroll view to the sheet for dismiss / shrink.
Set isDraggingEnabled: false to disable dragging entirely (button‑dismiss
only).
The sheet lifts out of the way when the keyboard appears — driven automatically
by MediaQuery.viewInsets. Tap the scrim once to close the keyboard, a second
time to dismiss (unless dismissOnHide: true).
Closures on BottomShelferPresentationManager fire during key lifecycle moments.
final manager = BottomShelferPresentationManager(
onDismiss: () => print('sheet dismissed'),
onGrabberDragBegan: () => print('grabber drag started'),
onGrabberDragEnded: () => print('grabber drag ended'),
onContentDragBegan: () => print('content drag started'),
onContentDragEnded: () => print('content drag ended'),
onDetentChanged: (index, height) => print('snapped to detent $index at ${height.round()}pt'),
);Drive the sheet to any detent from code via the controller.
// inside the sheet content:
final controller = BottomShelferScope.of(context);
controller.snapToHeight(320);
controller.dismiss();The sheet re‑derives its detent when the container size changes (device rotation, multi-window). Position clamping prevents off‑screen layouts.
Override the default metrics through BottomShelferLayoutConfiguration.
| Property | Default | Description |
|---|---|---|
maxSheetWidth |
430 | Clamps sheet width on wide screens |
maxHeightFraction |
0.9 | Caps sheet height as fraction of container |
grabberHitAreaHeight |
44 | Height of the draggable band |
grabberPillSize |
36 × 5 | Pill dimensions |
grabberPillBottomOffset |
12 | Distance from sheet edge |
grabberPillCornerRadius |
2.5 | Pill corner radius |
Sheet corner radius and dimming color are set directly on the manager.
final manager = BottomShelferPresentationManager(
cornerRadius: 24,
dimmingColor: Colors.indigo.withOpacity(0.2),
);final svg = await BottomShelferAssets.loadLogo();Run the demo (12 configurations) from the example/ directory:
cd example && flutter runMIT — see LICENSE.
jonikay89 — @jonikay89
