NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #1265 most downloaded on pub.dev
Sheet widgets with smooth motion and great flexibility. Also supports nested navigation in both imperative and declarative ways.
Last release 2 days ago
06 Oct 2026
Release timing varies
gaps range from 8 days to 4 months
Nearly every release is documented
notes for 49 of 51 stable releases
1 version withdrawn
withdrawn after publishing
3 years old
56 releases · first in 2024
This version migrates the package to material_ui . If your app still uses package:flutter/material.dart from the SDK, you may encounter runtime errors
This version migrates the package to material_ui. If your app still uses package:flutter/material.dart from the SDK, you may encounter runtime errors due to incompatibilities between widgets from the two Material packages, for example:
No Material widget found.
ListTile widgets require a Material widget ancestor within the closest LookupBoundary.Please follow the material_ui migration guide to migrate your app to material_ui.
The minimum supported Flutter SDK version is now 3.44.0, as required by material_ui.
One column per month.
fix: Prevent sheet from exceeding bounds when dragging non-overflowing scrollable content ( #613 ) - 12e3a1c
See the release note for more details.
build: Bump navigator_resizable from 3.0.2 to 3.1.0 to fix these issues: ( #605 ) - f315d5d
See the release note for more details.
fix: Avoid Widget Inspector crash on drag-disabled sheets ( #595 ) - beb86c7
fix: SheetContentScaffold semantics child order matches paint order so overlapping bars are not obscured by assistive technologies
See the release note for more details.
Add sheetVisibility to ModalSheetRouteMixin
ModalSheetRouteMixin.sheetVisibility has been added, an Animation<double> that reports how much of the sheet is visible in a modal route. It can be used, for example, to easily create custom modal barriers that change its opacity or blurriness based on the sheet's visibility, something like this:
See the API documentation and this example for more details.
See the release note for more details.
fix: Assertion error in SheetContentScaffold when height is zero ( #558 ) - ba7bd77
fix: False positive layout overflow assertion
fix: Avoid constraint violation and report layout overflow in SheetContentScaffold ( #539 ) - 488b569
This version mainly focuses on bug fixes to stabilize the package, but some small new features have also shipped. Breaking changes are marked with a 💥…
The first stable release of smooth_sheets!
This version mainly focuses on bug fixes to stabilize the package, but some small new features have also shipped. Breaking changes are marked with a 💥 — please follow the migration guides.
A new PagedSheetRouteTheme lets you set shared defaults for all routes in a PagedSheet. Place it above PagedSheet to configure scrollConfiguration, dragConfiguration, initialOffset, snapGrid, transitionDuration, and transitionsBuilder once, instead of repeating them on every route.
PagedSheetRouteTheme(
data: PagedSheetRouteThemeData(
transitionsBuilder: myTransitionBuilder,
snapGrid: mySnapGrid,
),
child: PagedSheet(
navigator: Navigator(...),
),
)Routes inherit from the theme when their parameter is null. Per-route values always take precedence.
scrollConfiguration: null on routes now means "inherit" 💥Previously, scrollConfiguration: null on a PagedSheetRoute or PagedSheetPage meant "no scroll-sheet integration." Now it means "inherit from PagedSheetRouteTheme." To explicitly disable scroll-sheet integration, use SheetScrollConfiguration.disabled:
BEFORE:
PagedSheetRoute(
scrollConfiguration: null, // No scroll-sheet integration
builder: (_) => MyContent(),
)AFTER:
PagedSheetRoute(
scrollConfiguration: SheetScrollConfiguration.disabled,
builder: (_) => MyContent(),
)dragConfiguration: null on routes now means "inherit" 💥The same rule as scrollConfiguration is now applied to dragConfiguration on PagedSheetRoute and PagedSheetPage. Specify SheetDragConfiguration.disabled instead of null to disable dragging for a route.
initialOffset, snapGrid, and transitionDuration on PagedSheetRoute and PagedSheetPage are now nullable. When null, they inherit from PagedSheetRouteTheme. The built-in defaults (when no theme is provided) are unchanged.
Previously, there was no way to manage a scroll controller for a scrollable widget inside a sheet from outside of it. A workaround was to use SheetScrollable and capture the controller in the builder callback, but this approach was not aligned with the widget's lifecycle.
With the updated SheetScrollable, you can now create a SheetScrollController outside the sheet (a specialized ScrollController) and attach it to SheetScrollable, just as you would with a regular ScrollController.
BEFORE:
ScrollController? scrollController;
Widget build(BuildContext context) {
return Sheet(
child: SheetScrollable(
builder: (context, controller) {
scrollController = controller;
return ListView(
controller: controller,
children: [...],
);
},
),
);
}AFTER:
late final SheetScrollController scrollController;
@override
void initState() {
super.initState();
scrollController = SheetScrollController();
}
void dispose() {
scrollController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
return Sheet(
child: SheetScrollable(
controller: scrollController,
child: ListView(
children: [...],
),
),
);
}Sheet.dragConfiguration is now non-nullable 💥Similar to PagedSheet, the dragConfiguration property on Sheet is now non-nullable. If you were passing null to disable dragging, use SheetDragConfiguration.disabled instead.
BEFORE:
Sheet(
dragConfiguration: null, // Disabled dragging
child: MyContent(),
)AFTER:
Sheet(
dragConfiguration: SheetDragConfiguration.disabled,
child: MyContent(),
)The spring parameter has been removed from the BouncingSheetPhysics constructor as part of a fix for #435. If you were using a custom spring, you can extend BouncingSheetPhysics and override the spring getter to return your custom value.
BEFORE:
BouncingSheetPhysics(spring: customSpring);AFTER:
class MyPhysics extends BouncingSheetPhysics {
MyPhysics({super.bounceExtent, super.resistance});
@override
SpringDescription get spring => customSpring;
}HitTestBehavior changed from translucent to opaque 💥The default hitTestBehavior in SheetDragConfiguration has changed from HitTestBehavior.translucent to HitTestBehavior.opaque, so that the sheet can be dragged out of the box even from transparent areas such as padding.
kDefaultSheetSpring has been removed from the public API 💥PagedSheet's shared elements (e.g., app-bar and bottom-bar) are now also affected by the current route's drag configuration (#500) 💥SteplessSnapGrid ignores on-screen keyboard appearance (#515) - b872c74Navigator.replace does not update position and size of PagedSheet (#508) - 9b38b6cSteplessSnapGrid ignores on-screen keyboard appearance (#515) - b872c74Navigator.replace does not update position and size of PagedSheet (#508) - 9b38b6cSee the release note for more details.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
This version introduces a padding property on Sheet and PagedSheet , giving you full control over how the sheet content responds to the keyboard, safe
This version introduces a padding property on Sheet and PagedSheet, giving you full control over how the sheet content responds to the keyboard, safe areas, or any other insets.
Previously, Sheet and PagedSheet offered two boolean flags — shrinkChildToAvoidDynamicOverlap and shrinkChildToAvoidStaticOverlap — to control whether a sheet automatically resizes its child to avoid the on-screen keyboard or screen notches. While they worked well in many cases, there are still cases those two flags can't cover — for example, a floating sheet with margins where the bottom margin changes depending on whether the keyboard is open.
A padding property has been added to Sheet and PagedSheet widgets to replace the two flags. This change also eliminates the automatic content resizing behavior, so you are now responsible for padding the sheet content to avoid the keyboard and screen notches.
Although it may sound like a downgrade, it enables you to build more complex layouts that couldn't be achieved with the legacy flags. Here's an example of such a layout where the sheet avoids screen notches when first displayed, then shifts itself above the keyboard when it opens while preserving a fixed amount of space between the keyboard and the sheet. Weirdly, this wasn't possible because shrinkChildToAvoidDynamicOverlap interfered with SheetViewport.padding, completely ignoring the padding when the keyboard was shown.
| Keyboard is closed | Keyboard is open |
|---|---|
See sheet_padding.dart for more examples.
You might wonder how Sheet.padding differs from SheetViewport.padding and wrapping the sheet content (Sheet.child) with a Padding widget from the Flutter SDK. While this interactive example is useful for understanding the differences visually, here's a TL;DR:
Sheet.padding to inset the content,SheetViewport.padding to add margin around the sheet itself, andPadding widget doesn't fit most cases.The shrinkChildToAvoidDynamicOverlap and shrinkChildToAvoidStaticOverlap flags on Sheet and PagedSheet have been removed. Please follow the instructions below to migrate from these two flags to the padding property. The basic rules are to replace:
shrinkChildToAvoidDynamicOverlap: true with a padding of MediaQuery.viewInsetsOf(context).bottomshrinkChildToAvoidStaticOverlap: true with a padding of MediaQuery.viewPaddingOf(context).bottomshrinkChildToAvoidDynamicOverlap: trueYou may have enabled shrinkChildToAvoidDynamicOverlap to automatically shift the sheet content upward to avoid the keyboard. It was true by default, so sheets that don't explicitly disable this flag should also migrate to the padding property as follows:
BEFORE
Sheet(
shrinkChildToAvoidDynamicOverlap: true,
child: ...,
);AFTER
Sheet(
padding: EdgeInsets.only(
bottom: MediaQuery.viewInsetsOf(context).bottom,
),
child: ...,
);shrinkChildToAvoidStaticOverlap: trueFollow this migration guide if you enabled shrinkChildToAvoidStaticOverlap to automatically pad the content to avoid screen notches at the bottom. It was false by default, so sheets that don't explicitly enable this flag are not affected by this change.
BEFORE
Sheet(
shrinkChildToAvoidStaticOverlap: true,
child: ...,
);AFTER
Sheet(
padding: EdgeInsets.only(
bottom: MediaQuery.viewPaddingOf(context).bottom,
),
child: ...,
);shrinkChildToAvoidDynamicOverlap: true and shrinkChildToAvoidStaticOverlap: trueBEFORE
Sheet(
shrinkChildToAvoidDynamicOverlap: true,
shrinkChildToAvoidStaticOverlap: true,
child: ...,
);AFTER
Sheet(
padding: EdgeInsets.only(
bottom: math.max(
MediaQuery.viewInsetsOf(context).bottom,
MediaQuery.viewPaddingOf(context).bottom,
),
),
child: ...,
);The following properties have also been removed:
SheetMetrics.viewportDynamicOverlap
MediaQuery.viewInsetsOf(context).bottom from descendant widgets of a sheet instead.SheetMetrics.viewportStaticOverlap
MediaQuery.viewPaddingOf(context).bottom from descendant widgets of a sheet instead.SheetLayoutSpec.viewportDynamicOverlap
MediaQuery.viewInsetsOf(context).bottom from descendant widgets of a sheet instead.SheetLayoutSpec.viewportStaticOverlap
MediaQuery.viewPaddingOf(context).bottom from descendant widgets of a sheet instead.SheetLayoutSpec.shrinkContentToAvoidDynamicOverlapSheetLayoutSpec.shrinkContentToAvoidStaticOverlap[!IMPORTANT]
shrinkChildToAvoidDynamicOverlapandshrinkChildToAvoidStaticOverlaphave been removed fromSheet,PagedSheet. Use thepaddingparameter instead.viewportDynamicOverlapandviewportStaticOverlaphave been removed fromViewportLayout,SheetLayoutSpec,SheetMetrics, and related classes.staticOverlap,dynamicOverlap,contentDynamicOverlap, andcontentStaticOverlapgetters have been removed fromSheetMetrics.SheetLayoutSpec.contentBaselinegetter has been removed.
See the release note for more details.
This version includes several new features, fixes and breaking changes (denoted with 💥).
This version includes several new features, fixes and breaking changes (denoted with 💥).
ModalSheetRoute.barrierBuilder has been added to modal routes and pages (thank you, @bqubique). This allows you to build a custom barrier for a modal sheet—for example, a blurred background. See this example for more practical usage.
ModalSheetRoute(
...
barrierBuilder: (route, dismissCallback) {
return GestureDetector(
onTap: dismissCallback,
child: BackdropFilter(
filter: ImageFilter.blur(sigmaX: 15.0, sigmaY: 15.0),
child: Container(color: Colors.black12),
),
);
},
);The way to configure the bouncing behavior of a sheet is now much more straightforward. There are only two parameters: bounceExtent and resistance. bounceExtent is the maximum number of pixels the sheet can be overdragged, and resistance is a factor that controls how easy or hard it is to overdrag the sheet by bounceExtent pixels. The higher the resistance value, the harder it is to overdrag further.
Use the tweak bouncing effect example to find the best values for your use case. Here are some examples:
| bounceExtent=20 | bounceExtent=80 | bounceExtent=140 |
|---|---|---|
| extent-20.mp4 | extent-80.mp4 | extent-140.mp4 |
| resistance=-10 | resistance=3 | resistance=20 |
|---|---|---|
| resistance-minus10.mp4 | resistance-3.mp4 | resistance-20.mp4 |
The following legacy APIs have been removed:
Unfortunately, there is no straightforward way to migrate from the old APIs to resistance and bounceExtent parameters while keeping exactly the same bouncing behavior.
A viewportBuilder has been added to modal sheet routes and pages. It builds a SheetViewport for a modal sheet, allowing SheetViewport.padding to depend on BuildContext and dynamically change based on system UI elements like the on-screen keyboard.
You may think this change isn't very useful since the current SheetViewport only has a padding property. However, as more features like #3 are added to SheetViewport, you'll see more benefits from this change.
The viewportPadding property has been removed from modal sheet routes and pages. Use viewportBuilder instead and specify the padding directly via SheetViewport.padding.
BEFORE
ModalSheetRoute(
viewportPadding: EdgeInsets.only(
top: MediaQuery.viewPaddingOf(context).top,
),
builder: (context) => Sheet(...),
);AFTER
ModalSheetRoute(
viewportBuilder: (context, child) {
return SheetViewport(
padding: EdgeInsets.only(
top: MediaQuery.viewPaddingOf(context).top,
),
// The child is the widget built by the builder callback.
child: child,
);
},
builder: (context) => Sheet(...),
);This release also includes several improvements to sheet behaviors in response to user gestures:
SheetScrollConfiguration.thresholdVelocityToInterruptBallisticScroll has been removed. This option was part of the public API and configurable, but it never actually affected the sheet's behavior.
[!IMPORTANT]
- The
paddingproperties have been removed from modal sheet routes and pages.BouncingBehaviorand its subclasses have been removed.behaviorandfrictionCurvehave been removed.SheetScrollConfiguration.thresholdVelocityToInterruptBallisticScrollwas removed.
See the release note for more details.
Flutter SDK 3.29+ is now required.
Important
SwipeDismissSensitivity.minDragDistance has been removed.Reported in #303, fixed in #415 thanks to @bjartebore
Previously, we used SwipeDismissSensitivity.minDragDistance to define how many pixels the user had to drag down the modal sheet to close it. However, since it only accepted a threshold distance in logical pixels, it was difficult to create a consistent UX across various device sizes and sheet sizes.
SwipeDismissSensitivity.dismissalOffset has been introduced as a replacement for minDragDistance and tackle this problem. It allows us to define the modal's dismissal threshold in terms of SheetOffset, below which the sheet will be dismissed when the drag ends. This change provides much greater control over when sheets should be dismissed, allowing thresholds to depend on percentages, absolute pixels, or even custom logic that adapts to content size or viewport dimensions.
Usage:
// Dismiss if only 40% or less of the sheet is visible when the drag ends
const SwipeDismissSensitivity(dismissalOffset: SheetOffset(0.4));
// Dismiss if only 200 pixels or less of the sheet is visible when the drag ends
const SwipeDismissSensitivity(dismissalOffset: SheetOffset.absolute(200));
// Dismiss if the sheet is in the bottom half of the screen when the drag ends
const SwipeDismissSensitivity(dismissalOffset: SheetOffset.proportionalToViewport(0.5));
// Custom threshold for more complex use cases
const SwipeDismissSensitivity(dismissalOffset: CustomThreshold());
class CustomThreshold implements SheetOffset {
const CustomThreshold();
@override
double resolve(ViewportLayout metrics) {
return max(metrics.contentSize.height * 0.5, 80);
}
}Unfortunately, there's no straightforward way to migrate from minDragDistance to dismissalOffset as they represent different thresholds. While minDragDistance describes how many pixels the user has to drag the sheet to dismiss the modal, dismissalOffset defines the distance from the bottom edge of the route's viewport to the top edge of the sheet, below which the sheet will dismiss when the drag ends.
This is a special case, but if you know the sheet's height in advance, it's possible to migrate to the new API while keeping the current behavior. For example, if the sheet's height is 500 and the minDragDistance is 100, you can set dismissalOffset to SheetOffset.absolute(500 - 100).
Full Changelog: v0.14.0...v0.15.0
[!IMPORTANT]
- Added
SwipeDismissSensitivity.dismissalOffsetandSwipeDismissSensitivity.minDragDistancewas removed instead.- Requires Flutter SDK 3.29 or higher.
See the release note for more details.
Cupertino Modal Sheet Overlay Effect
Reported in #25, fixed in #403
We've added support for toning overlay effects on Cupertino-style modal sheets when stacking them, matching native iOS behavior. The new overlayColor parameter in CupertinoModalSheetPage and CupertinoModalSheetRoute allows applying a subtle overlay to background sheets when another sheet is presented, creating a more authentic iOS experience and improving visual hierarchy, especially in dark mode.
Usage:
CupertinoModalSheetPage(
overlayColor: const Color(0x33ffffff), // A translucent white color
child: MySheetContent(),
)overlayColor: null |
overlayColor: Color(0x33ffffff) |
|---|---|
| without-overlay-color.mp4 | with-overlay-color.mp4 |
Reported in #264, fixed in #402
We've added support for pull-to-refresh functionality and overscroll effects within sheets through the new delegateUnhandledOverscrollToChild flag in SheetScrollConfiguration. When enabled, this flag allows overscroll deltas that aren't handled by the sheet's physics to be passed to child scrollable widgets, enabling RefreshIndicator and BouncingScrollPhysics effects to work seamlessly within sheet content.
This feature maintains backward compatibility and requires explicit opt-in, ensuring no impact on existing code.
pulltorefresh-in-sheet.mp4Reported in #399, fixed in #400
Fixed an issue where sheets would not maintain their proper position when the app window was resized, particularly when dragging the bottom border to expand the window downward. Previously, sheets would appear to "float" rather than staying correctly positioned relative to the window boundaries.
This issue was especially noticeable on desktop platforms and also occurred on Android when running in Picture-in-Picture mode with keyboard interactions. The fix ensures that sheets now properly track window size changes and maintain their relative position, providing a more consistent user experience across different window configurations.
Record_2025-07-01-01-33-17.mp4Full Changelog: v0.13.0...v0.14.0
See the release note for more details.
feat: Add SheetScrollHandlingBehavior for precise control over scroll gesture handling (#393) - ee7f2a6
See the release note for more details.
feat: Add SheetPopScope to enable/disable the swipe gesture in modals from within build method (#359) - 6766534
See the release note for more details.
fix: SheetNotification not dispatched during PagedSheet route transitions (#352) - 609ac4b
See the release note for more details.
fix: Assertion error when push CupertinoModalSheetRoute during closing animation (#347) - 0dbf6ee
See the release note for more details.
fix: PagedSheet cannot be dragged when the drag starts at shared top/bottom bar built in builder callback (#323) - 2ba8d35
See the release note for more details.
fix: Bottom bar is hidden despite BottomBarVisibility.always(ignoreBottomInset: true) (#313) - faa7883
BottomBarVisibility.always(ignoreBottomInset: true) (#313) - faa7883See the release note for more details.
fix: Initial offset of PagedSheet is ignored when using auto_route (#310) - fd83555
See the release note for more details.
This version contains breaking changes. See the migration guide for more details.
This version contains breaking changes. See the migration guide for more details.
[!IMPORTANT] Version 0.11.x requires Flutter SDK version 3.27.0 or higher.
StickyBottomBarVisibility positioned incorrectly for constrained sheets #297go_router.go() method to close a sheet don't seems to reset animation state #211margin property to sheet widget #282CupertinoModalSheetRoute and Page with ModalRoute.delegatedTransition #293ScrollableSheet and DraggableSheet into a single widget to simplify the API and codebase #285NavigationSheet #280NavigationSheet independent of NavigatorObserver #172Nothing published for this version
Nothing published for this version
This version contains breaking changes. See the migration guide for more details.
This version contains breaking changes. See the migration guide for more details.
Add SwipeDismissSensitivity, a way to customize sensitivity of swipe-to-dismiss action on modal sheet
SwipeDismissSensitivity, a way to customize sensitivity of swipe-to-dismiss action on modal sheet (#222)Fix: Press-and-hold gesture in PageView doesn't stop momentum scrolling
Fix: Keyboard visibility changes disrupt route transition animation in NavigationSheet
Fix: Sometimes touch is ignored when scrollable sheet reaches edge
This version contains some breaking changes. See the migration guide for more details.
This version contains some breaking changes. See the migration guide for more details.
Fix: Opening keyboard interrupts sheet animation
Fix: Cupertino style modal transition not working with NavigationSheet
This version contains some breaking changes. See the migration guide for more details.
This version contains some breaking changes. See the migration guide for more details.
Fix: DropdownButton doesn't work in NavigationSheet
Fix: Attaching SheetController to NavigationSheet causes "Null check operator used on a null value"
Fix: Unwanted bouncing effect when opening keyboard on NavigationSheet
This version contains some breaking changes. See the migration guide for more details.
This version contains some breaking changes. See the migration guide for more details.
< 3.22.0 (#141)This version contains some breaking changes. See the migration guide for more details.
This version contains some breaking changes. See the migration guide for more details.
Fix an assertion error when specific page transition scenarios in declarative 'NavigationSheet'
Fix a crash during the first build of NavigationSheet with a path that contains multiple routes such as /a/b/c
NavigationSheet with a path that contains multiple routes such as /a/b/c (#109)Re-export NavigationSheetRoute that is unintentionally omitted in v0.5.0
NavigationSheetRoute that is unintentionally omitted in v0.5.0 (#110)This version contains some breaking changes. See the migration guide for more details.
This version contains some breaking changes. See the migration guide for more details.
Add new SheetNotifications for drag events
Fix mistakes in the documentation of BottomBarVisibility and ConditionalStickyBottomBarVisibility which may mislead readers.
BottomBarVisibility and ConditionalStickyBottomBarVisibility which may mislead readers.Add BottomBarVisibility widgets (#15, #19)
BottomBarVisibility widgets (#15, #19)Fix crash when clicking on the modal barrier while dragging the sheet
- Add InterpolationSimulation
InterpolationSimulation (#55)- Documentation updates
- Documentation updates
Add iOS 15 style modal sheet transition
settings and fullscreenDialog params to the constructors of modal sheet routes and pages (#28)enablePullToDismiss (#44)Add a showcase that uses TextFields in a sheet
- Initial release
Your coding agent can read these notes before it upgrades. Set up the MCP server →