quiet_dock
A floating glass bottom dock for Flutter — the mobile navigation shell, the swipeable page sliding and the tab-switching logic in one widget.
quiet_dock

/// Note: The GIF may look laggy, but the actual animation is smooth. /// The GIF has reduced frames to keep the file size smaller.
- Floating frosted dock with an animated sliding pill indicator
- Swipe left/right to slide between screens, perfectly in sync with the dock
- One function handles every tab change: tap, swipe, quick-grid tile or code
- Optional center action that pops an animated quick grid of extra destinations
- Automatic side navigation rail on tablet/desktop widths
- Zero dependencies beyond Flutter; works with any router (go_router, Navigator, none)
Install
dependencies:
quiet_dock: ^0.1.0
Quick start
import 'package:quiet_dock/quiet_dock.dart';
QuietDockScaffold(
destinations: const [
QuietDockDestination(
icon: Icons.home_outlined,
selectedIcon: Icons.home_rounded,
label: 'Home',
),
QuietDockDestination(icon: Icons.checklist_outlined, label: 'Todos'),
QuietDockDestination(icon: Icons.notes_outlined, label: 'Notes'),
QuietDockDestination(icon: Icons.settings_outlined, label: 'Settings'),
],
pageBuilder: (context, index) => pages[index],
onDestinationSelected: (index) => debugPrint('tab $index'),
);
That is the whole integration: dock, page sliding, keep-alive pages and the wide-screen rail.
Quick grid center action
Drop extra destinations behind a center trigger that springs open above the dock:
QuietDockScaffold(
destinations: destinations,
pageBuilder: (context, i) => pages[i],
centerAction: QuietDockCenterAction(
columns: 3,
items: [
QuickGridItem(icon: Icons.flag_rounded, label: 'Goals', onTap: openGoals),
QuickGridItem(icon: Icons.school_rounded, label: 'Courses', onTap: openCourses),
// ...any number of tiles
],
),
);
One function for tab switching
Dock taps, swipes, quick-grid tiles and QuietDockController.goToIndex all
funnel through the same internal selector, which updates the index, slides (or
jumps, when the distance is greater than one) the page, and calls
onDestinationSelected exactly once. Put your routing there:
final controller = QuietDockController();
QuietDockScaffold(
controller: controller,
destinations: destinations,
pageBuilder: (context, i) => pages[i],
onDestinationSelected: (index) => context.go(routes[index]),
);
controller.goToIndex(2); // same path as a tap
go_router
quiet_dock does not depend on a router. With go_router, wrap the scaffold in
a ShellRoute and drive it from the callback:
ShellRoute(
builder: (context, state, child) {
final location = state.uri.path;
final index = routes.indexWhere(location.startsWith);
return QuietDockScaffold(
initialIndex: index < 0 ? 0 : index,
destinations: destinations,
pageBuilder: (context, i) => pages[i],
onDestinationSelected: (i) => context.go(routes[i]),
);
},
routes: [...],
);
Theming
Colors default to the ambient ThemeData (light and dark) and every value is
overridable:
QuietDockScaffold(
theme: const QuietDockTheme(
width: 320,
height: 60,
radius: 30,
frosted: true,
blur: 22,
showLabels: true,
hapticFeedback: true,
),
// ...
);
Other pieces
| Widget | Use it for |
|---|---|
QuietDockScaffold |
Complete shell: dock + sliding pages + rail |
QuietDock |
Just the dock bar, over your own body |
QuietDockRail |
Just the wide-screen rail |
QuietQuickGrid |
The popover grid on its own |
Example
cd example
flutter run
License
MIT
Libraries
- quiet_dock
- A floating glass bottom dock for Flutter apps, with swipeable page sliding, a quick-grid center action and a wide-screen navigation rail.