Full Width Dropdown Button
A polished, animated full-width dropdown for Flutter with nested submenus, smart overlay positioning, rich leading widgets, hover feedback, and smooth motion.
Features
- Full-width overlay menu with configurable trigger size
- Opens below first and flips above only when space is limited
- Tracks the trigger while the page scrolls
- Simple string API and rich nested-item API
- Animated nested submenus
- Widget-based leading content for icons, SVGs, avatars, and more
- Destructive parent and sub-items
- Mouse hover feedback for desktop and web
- Haptic feedback on supported platforms
- Custom trigger widget or SVG asset trigger
- Scale, fade, slide, and expansion animations
Installation
dependencies:
full_width_dropdown_button: ^0.2.4
Then import the package:
import 'package:full_width_dropdown_button/full_width_dropdown_button.dart';
Quick start
FullWidthDropdownButton(
child: const Icon(Icons.tune_rounded),
items: const ['Newest', 'Oldest', 'Popular'],
onSelected: (value) {
debugPrint(value);
},
)
Rich nested menu
Use FullWidthDropdownButton.rich when you need leading widgets, submenus, or destructive actions.
FullWidthDropdownButton.rich(
child: const Icon(Icons.filter_alt_rounded),
dropdownItems: [
const DropdownItem(
label: 'Food type',
leading: Icon(Icons.restaurant_rounded, size: 16),
subItems: ['Soup', 'Grill', 'Stir-fry'],
),
const DropdownItem(
label: 'Meat',
leading: Icon(Icons.lunch_dining_rounded, size: 16),
subItems: [
DropdownSubItem(label: 'Beef'),
DropdownSubItem(label: 'Chicken'),
DropdownSubItem(label: 'Remove filter', isDestructible: true),
],
),
const DropdownItem(label: 'Popular'),
const DropdownItem(
label: 'Clear all',
isDestructible: true,
leading: Icon(Icons.delete_outline_rounded, size: 16),
),
],
onItemSelected: (parent, sub) {
debugPrint(sub == null ? parent : '$parent > $sub');
},
)
SVG trigger
FullWidthDropdownButton(
iconAsset: 'assets/filter.svg',
items: const ['A', 'B', 'C'],
onSelected: debugPrint,
)
Register the SVG in your application's pubspec.yaml before using it as an asset trigger.
Customize the trigger
FullWidthDropdownButton.rich(
width: 52,
height: 52,
padding: const EdgeInsets.all(14),
decoration: BoxDecoration(
color: Colors.grey.shade100,
borderRadius: BorderRadius.circular(100),
),
openDecoration: BoxDecoration(
color: Colors.black,
borderRadius: BorderRadius.circular(100),
),
iconColor: Colors.grey,
openIconColor: Colors.white,
child: const Icon(Icons.menu_rounded),
dropdownItems: const [DropdownItem(label: 'Option')],
onItemSelected: (parent, sub) {},
)
Main options
| Option | Purpose |
|---|---|
child |
Custom trigger widget |
iconAsset |
SVG asset used as the trigger when child is not supplied |
width / height |
Trigger dimensions |
padding |
Trigger content padding |
decoration |
Trigger decoration while closed |
openDecoration |
Trigger decoration while the menu is open |
iconColor / openIconColor |
Trigger icon colors for closed/open states |
selectedItem |
Current selected label passed to the menu |
onClose |
Callback fired when an open dropdown closes |
The default constructor accepts List<String>. The .rich constructor accepts List<DropdownItem> and reports both the parent and optional child value.
Overlay behavior
The menu uses the current screen width with a 16 px horizontal margin. It initially measures only the collapsed parent rows, which keeps the dropdown down-first instead of flipping upward just because a submenu could expand later.
Because the menu is rendered in an Overlay and attached with a LayerLink, it continues following its trigger while the surrounding page scrolls.
Platform notes
The widget uses standard Flutter overlay and pointer APIs, so it is suitable for mobile, web, and desktop Flutter applications. Hover feedback is naturally most useful on mouse-based platforms, while haptics depend on platform support.
Contributing
Bug reports and feature ideas are welcome in GitHub Issues. For code contributions, see CONTRIBUTING.md.
License
MIT — see LICENSE.