draggable_panel 4.1.0
draggable_panel: ^4.1.0 copied to clipboard
A floating panel window — drag it anywhere, spring-snap to the nearest side, stash it off the edge, tap to grow it in place.
4.1.0 #
Features
- PanelDragArea: marks the part of an expanded panel that drags the window, so a scrollable inside it keeps its own swipes.
Fixes
- An expanded panel no longer halves the platform touch slop, which had it taking drags meant for a scrollable inside it.
Changed
- The DraggableActionPanel header stays put while the grid scrolls under it, and doubles as the panel's drag area.
- With a drag area declared, a tap outside it is left to the content instead of collapsing the panel.
4.0.0 #
A rewrite. The panel is now a floating window: drag it anywhere, release it and it springs to the nearest side by projected velocity, flick it past an edge to park it off-screen, tap it to grow in place into a full panel. Material 3 visuals, spring-based motion throughout.
Breaking changes
DraggablePanelnow takescollapsedBuilder+expandedBuilderand arbitrary content. The icons-and-buttons shape lives on as theDraggableActionPanelpreset. SeeMIGRATION.mdfor the full mapping.onPositionChanged(x, y)becameonPlacementChanged(PanelPlacement). Stored pixel positions cannot be converted and should be dropped.- Every controller method that took a screen size is gone:
forceDock,hidePanel,togglePanel,toggleMainButton,relayoutandrecomputeDockSidewere layout math leaking into a state object. - Interaction flags moved off the controller onto
PanelBehavior, passed to the widget. DraggablePanelThemebecameDraggablePanelThemeData, aThemeExtensionwith nullable tokens, so a call-site override no longer clobbers an app-wide one. Sub-themes flattened intoDraggableActionPanelThemeData.DraggablePanelMotion(durations and curves) becamePanelMotionSpec(springs). There is no mechanical mapping — a tween cannot carry entry velocity or be redirected mid-flight.panelSwitchInCurveandpanelSwitchOutCurvewent with it; neither had any effect in 3.x.- Removed:
MultiValueListenableBuilder,TooltipSnackBar,DockType,PanelState, and the already-deprecatedpanelAnimDuration,dockAnimDurationandmovementSpeed. - The panel must be given the whole window, since that is what it resolves its placement against. A smaller box still paints and still takes its gestures, but reports the mistake once in debug rather than leaving it to be found by eye.
- Minimum Flutter is now 3.32 (Dart 3.8).
Added
- Spring physics throughout: velocity projection, a critically damped 400 ms settle, and the iOS rubber band. Motion is interruptible — grabbing a moving panel folds its momentum into the next throw, and reversing an expansion halfway overshoots, turns around and comes back.
- Grow-in-place expansion anchored at the corner the panel occupies, and a
snapPolicychoosing between sides, corners, and free placement. - Edge parking: push the panel against a side and it stays there as a grab-able tab, pull it back and it returns. Both are ordinary drags rather than separate gestures, and an open panel closes on its way into the park. A tab moved along to another edge re-parks there instead of opening, so the two settings that drop the collapsed window still let you just put the panel somewhere else.
- Three resting stages, two of them optional.
stashable: falsedrops the park,collapsible: falsedrops the small window between tab and panel, andexpandOnUnstash: trueopens the panel straight out of a park. PanelPlacement— resolution-independent resting positions with JSON round-tripping, so a placement saved on a tablet restores on a phone.PanelBehaviorfor interaction flags, covering idle parking, tap-outside parking, keyboard avoidance, haptics and the snap policy.- Full accessibility: per-corner custom semantics actions, keyboard corner
navigation, a dismiss action, screen-reader-aware drag suppression, honoured
reduced motion, and
PanelSemanticsfor localizable copy. - Committed-moment haptics, independent of the motion preference.
DraggablePanelScopefor reaching the controller from panel content.- A theme token for every visual the panel paints, frosted glass through
surfaceFilter, and the springs themselves. - The
DraggableActionPanelpreset — an action grid with captions and badges, a header with a close control, scrolling content, and a builder for every part.
Changed
- Rotation, resize, split-screen and the keyboard re-place the panel by re-resolving its placement, carrying velocity, instead of teleporting it.
Performance
- Motion is paint-only and isolated behind its own repaint boundary. A frame of movement costs zero widget builds, zero layouts, and no repaint of the application behind the panel — all three asserted by regression tests.
Fixed
- Panel content sits inside a transparent
Material, so a bareTextin a builder inherits the app's text style instead of rendering as oversized debug type, and anInkWellfinds something to ink on. - Drag velocity is no longer discarded on release; a flick and a slow drop now differ.
- Dragging past an edge stretches against a rubber band and springs back, instead of the panel stopping dead against the bound mid-gesture.
- Theme changes crossfade the panel along with the rest of the app.
3.0.0 #
Major release: open/hide stability, adaptive content-sized layout, and end-to-end customization.
Fixes
- Deterministic button hide/reveal — no more late or missing hide on open.
- Resize (keyboard/rotation/split-screen) no longer pulls a hidden button back on-screen.
- Single-frame open (removed the
awaitbetween hide and reveal). - Off-screen position no longer persisted via position listeners.
- No crash with an empty
itemslist.
Layout
- Panel sizes to its content in both axes;
panelWidthis now the maximum. - Item grid balances columns so the last row isn't half-empty; height caps to free space and scrolls.
- Panel anchors flush to the button's inner edge.
Customization
- Motion via
DraggablePanelTheme.motion(durations + curves). - Behavior flags on the controller:
tapToToggle,draggable,closeOnTapOutside. - Content builders:
itemBuilder,buttonBuilder,handleBuilder. - Shell builders:
itemFrameBuilder,buttonFrameBuilder. - Panel builders:
panelBuilder(surface),panelContentBuilder(layout). - Custom tooltip via
onShowTooltip. - Per-item styling on
DraggablePanelItem:color,foregroundColor,badgeColor,badgeLabel. - New theme tokens: handle drag icon/size, item
iconSize, buttonlabelStyle, tooltip text style.
Breaking changes
- Durations moved to
DraggablePanelTheme.motion; controllerpanelAnimDuration/dockAnimDurationdeprecated (no effect). DraggablePanelController.movementSpeeddeprecated in favor ofanimateMovement.DraggablePanelController.toggleMainButtonnow returnsvoidinstead ofFuture<void>.
2.0.2 #
- Fixed tooltip text color not adapting to light/dark theme.
2.0.0 #
- Sub-themes for items, buttons, tooltip, and drag handle.
- Layout properties:
panelWidth,panelContentPadding,itemSpacing,buttonSpacing,sectionSpacing. - Material 3 dark theme support with surface-based default colors.
- Border no longer affects content layout.
- No breaking changes — existing code works without modifications.
1.4.3 #
Fixes
- Fixed panel overflow when
panelBorderis set: Panel height now accounts for border width when calculating items per row.
1.4.2 #
Major theme refactor and customization improvements.
What's new
- DraggablePanelTheme: Introduced a comprehensive theme class to centralize all styling properties.
- Enhanced Customization: You can now customize every aspect of the panel, including button colors, shadows, borders, and more, via the
themeproperty. - Simplified API: Removed individual style arguments from
DraggablePanelin favor of thethemeobject, making the API cleaner and more consistent.
Improvements
- Added widget tests to ensure reliability.
- Updated documentation with new usage examples.
1.3.1 #
Code quality improvements and enhanced documentation.
What's new
- Enhanced documentation: comprehensive dartdoc comments with usage examples and parameter descriptions across all public APIs.
- Improved tooltips: better theme adaptation and modern appearance for item/button tooltips.
Improvements
- Better code organization and widget decomposition for improved maintainability.
- Optimized performance with reduced widget rebuilds and better const usage.
- Enhanced position listener handling with improved lifecycle safety.
- Stricter code quality with comprehensive lint rules and zero analysis issues.
Migration notes
- No breaking changes. All existing code works as expected.
1.2.0 #
Desktop/Web resize stability, auto-docking, and controller improvements.
What's new
- Auto-dock on window resize: the draggable button now snaps to the nearest edge when the window is resized on desktop/web, matching the expected behavior.
- Stable dock side: introduced
isDockedRightinDraggablePanelControllerto track the docked side explicitly. This prevents side flipping during resizes and ensures consistent alignment when the button is off-screen. - Resize handling in widget:
DraggablePanelnow observesdidChangeMetricsand reclamps/repositions without long animations during resize.
Changes
DraggablePanelController:- Added
bool get isDockedRightand internal tracking updated inforceDock(). hidePanel(),togglePanel(), andtoggleMainButton()now useisDockedRightinstead of recomputing side from current left/width.- Added
recomputeDockSide(pageWidth)helper for future scenarios where side needs recalculation without moving.
- Added
DraggablePanel:- Uses
controller.isDockedRightin UI instead of deducing side vialeft > width/2. - On init, initial position is clamped and, if closed, docked and panel hidden off-screen on the correct side.
- On resize, positions are clamped, side is docked, and open/closed panel positions recalculated accordingly with zero-duration movement during the resize frame.
- Uses
Fixes
- Panel and button no longer drift or jump when resizing the window; the open panel stays aligned to its edge, and the closed panel remains fully off-screen on the correct side.
- Prevented duplicate/misleading side calculations that caused inconsistencies during transitions.
Performance and cleanup
- Reduced unnecessary rebuilds during resize by batching updates and suppressing long animations for these events.
- Minor readability improvements (clearer border condition, removal of unused code, better ordering of resize operations).
Migration notes
- No breaking API changes. If you previously derived side from
draggablePositionLeft, consider readingcontroller.isDockedRightfor consistency with the new logic.
1.1.0 #
- Added: Position change listener API in
DraggablePanelController(addPositionListener/removePositionListener). - Added: Public
dockBoundarygetter for consistent boundary logic across widget and controller. - Changed:
toggle()now respects currentpanelState(notinitialPanelState). Auto-toggle on mount removed to preserve user state. Initial position is clamped and (when starting closed) docked to the nearest edge. - Fixed: Panel no longer resets to default after visibility toggles; duplicate position callbacks removed; unified docking logic.
- Performance: Batched x/y updates during drag via
setPosition(x, y); reduced redundant notifications and rebuilds; lifecycle safety (mounted checks) and controller rewire indidUpdateWidget.
1.0.6 #
- Added tooltip snackbar when long press on the panel buttons and items.
- Records replaced by
DraggablePanelItemandDraggablePanelButtonmodels withdescriptionfield for tooltips.
1.0.3 #
- Removed
copymethod fromDraggablePanelController. It was not necessary. Issue was fixed by another way. Please if you use your ownDraggablePanelControllerdon't forget to dispose it.
1.0.2 #
- Added
copymethod toDraggablePanelController. It fixes the issue when you hide and re-show the panel.
1.0.1 #
- In this update, I added the
DraggablePanelControllerto give you the ability to control the panel directly outside of this widget. Just create it and pass it to theDraggablePanelwidget. See example.
1.0.0 #
- Changed alignment of
Wrapinside DraggablePanel.
0.0.9 #
- Added new optional param
panelHeight. This param is used to set the height of the panel. If not set, the panel will take the height of the child widget based on item's and button's length.
0.0.8 #
- The panel size calculation has been changed.
0.0.6 #
- Added web support with essential configuration for PWA functionality.
- Improved draggable panel logic by introducing better state management and optimizing boundary checks.
- Fixed issues with initial panel positioning and docking behavior.
- Simplified and cleaned up redundant code for better maintainability.
0.0.5 #
- Now
childis nullable inDraggablePanelwidget. This is useful when you want to useDraggablePanelinside other stack widgets.
0.0.4 #
- The
DraggablePanelItemandDraggablePanelButtonmodels were removed and replaced withRecord. This was done to make the package easier to use. If you were usingDraggablePanelin a package, you would need to import models for others that use your same package. Now, this is not necessary.
0.0.3 #
- Initial release.
