Menu Kit
Animated dropdown and fan menus for Flutter with ready-to-use directional and radial presets.
Menu Kit gives you small, composable menu widgets that work with any trigger and any child widgets. Use it for floating action menus, tool palettes, context actions, quick navigation, and radial command menus.
Features
DropDownMenufor linear left, right, up, down, and bidirectional layouts.FanMenufor circular and half-curve radial layouts.- Custom trigger builder with a simple
toggleMenucallback. - Works with any Flutter widget as a menu item.
- Configurable
offset,childrenMargin,triggerMargin, andradius. - Lightweight
FlowDelegateanimations with no platform-specific code.
Installation
Add Menu Kit to your pubspec.yaml:
dependencies:
menu_kit: ^1.0.0
Then fetch packages:
flutter pub get
Import
import 'package:menu_kit/menu_kit.dart';
Quick Start
Create and dispose an AnimationController, then pass it to a menu widget.
class QuickMenu extends StatefulWidget {
const QuickMenu({super.key});
@override
State<QuickMenu> createState() => _QuickMenuState();
}
class _QuickMenuState extends State<QuickMenu>
with SingleTickerProviderStateMixin {
late final AnimationController controller;
@override
void initState() {
super.initState();
controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 350),
);
}
@override
void dispose() {
controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return DropDownMenu(
controller: controller,
preset: MenuPreset.centerOpeningDown,
trigger: (toggleMenu) => FloatingActionButton(
onPressed: toggleMenu,
child: const Icon(Icons.add),
),
children: const [
FloatingActionButton.small(
heroTag: 'home',
onPressed: null,
child: Icon(Icons.home),
),
FloatingActionButton.small(
heroTag: 'favorite',
onPressed: null,
child: Icon(Icons.favorite),
),
],
);
}
}
Examples
Run the included example app:
cd example
flutter run
The example shows every dropdown and fan preset in grouped tabs, including custom spacing and offset controls.
Dropdown Menu
Use DropDownMenu when actions should spread along a straight line.
DropDownMenu(
controller: controller,
preset: MenuPreset.centerOpeningRight,
offset: Offset.zero,
childrenMargin: const EdgeInsets.all(6),
trigger: (toggleMenu) => IconButton.filled(
onPressed: toggleMenu,
icon: const Icon(Icons.add),
),
children: menuActions,
)
Dropdown Presets
MenuPreset includes center, edge, corner, and bidirectional layouts:
centerOpeningLeft, centerOpeningRight, centerOpeningUp,
centerOpeningDown, leftCenterOpeningRight, leftCenterOpeningUp,
leftCenterOpeningDown, rightCenterOpeningLeft, rightCenterOpeningUp,
rightCenterOpeningDown, topCenterOpeningLeft, topCenterOpeningRight,
topCenterOpeningDown, bottomCenterOpeningLeft,
bottomCenterOpeningRight, bottomCenterOpeningUp, topLeftOpeningRight,
topLeftOpeningDown, topRightOpeningLeft, topRightOpeningDown,
bottomLeftOpeningRight, bottomLeftOpeningUp, bottomRightOpeningLeft,
bottomRightOpeningUp, centerOpeningLR, centerOpeningTD,
leftCenterOpeningTD, rightCenterOpeningTD, topCenterOpeningLR, and
bottomCenterOpeningLR.
| Demo | Description |
|---|---|
![]() |
Center Opening (Down)DropDownMenu(preset: MenuPreset.centerOpeningDown, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Opening (Left)DropDownMenu(preset: MenuPreset.centerOpeningLeft, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Opening (Right)DropDownMenu(preset: MenuPreset.centerOpeningRight, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Opening (Up)DropDownMenu(preset: MenuPreset.centerOpeningUp, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Opening (Left and Right)DropDownMenu(preset: MenuPreset.centerOpeningLR, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Opening (Top and Down)DropDownMenu(preset: MenuPreset.centerOpeningTD, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
Fan Menu
Use FanMenu when actions should spread around the trigger in an arc.
FanMenu(
controller: controller,
preset: FanMenuPreset.circular,
radius: 24,
trigger: (toggleMenu) => FloatingActionButton(
onPressed: toggleMenu,
child: const Icon(Icons.add),
),
children: menuActions,
)
Fan Presets
FanMenuPreset includes circular, leftHalfCurve, rightHalfCurve,
topHalfCurve, bottomHalfCurve, centerTopHalf, centerBottomHalf,
centerLeftHalf, and centerRightHalf.
| Demo | Description |
|---|---|
![]() |
Circular Fan MenuFanMenu(preset: FanMenuPreset.circular, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Top Half Fan MenuFanMenu(radius: 20, preset: FanMenuPreset.centerTopHalf, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Bottom Half Fan MenuFanMenu(radius: 20, preset: FanMenuPreset.centerBottomHalf, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Left Half Fan MenuFanMenu(radius: 20, preset: FanMenuPreset.centerLeftHalf, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Center Right Half Fan MenuFanMenu(radius: 20, preset: FanMenuPreset.centerRightHalf, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions) |
| Demo | Description |
|---|---|
![]() |
Customize Item Spacing with radiusFanMenu(radius: 30, preset: FanMenuPreset.centerLeftHalf, offset: Offset.zero, controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions)Smaller radius values keep items closer. Larger values increase distance from the trigger. |
Customization
Use offset to move the whole menu after the preset alignment is calculated:
| Demo | Description |
|---|---|
Custom Menu Position Using offsetDropDownMenu(preset: MenuPreset.centerOpeningDown, offset: const Offset(70, -150), controller: controller, trigger: (toggleMenu) => FloatingActionButton(onPressed: toggleMenu, child: const Icon(Icons.add)), children: menuActions)Positive X moves right, negative X moves left, positive Y moves down, and negative Y moves up. |
Use childrenMargin for item spacing and triggerMargin when the trigger needs
different spacing from the menu children.
DropDownMenu(
controller: controller,
preset: MenuPreset.bottomCenterOpeningUp,
childrenMargin: const EdgeInsets.all(8),
triggerMargin: const EdgeInsets.all(12),
offset: const Offset(0, -24),
trigger: (toggleMenu) => IconButton.filled(
onPressed: toggleMenu,
icon: const Icon(Icons.menu),
),
children: menuActions,
)
API Reference
BaseMenu
BaseMenu is the shared abstract base for Menu Kit widgets.
controller: requiredAnimationControllerthat drives opening and closing.trigger: required builder that receivesVoidCallback toggleMenu.children: required list of menu action widgets.childrenMargin: margin around each child. Defaults toEdgeInsets.all(5).triggerMargin: optional trigger margin. Defaults tochildrenMargin.offset: translation applied to the whole menu. Defaults toOffset.zero.
DropDownMenu
DropDownMenu extends BaseMenu and adds:
preset: requiredMenuPresetthat controls anchor and spread direction.
FanMenu
FanMenu extends BaseMenu and adds:
preset: requiredFanMenuPresetthat controls the circular or half-curve layout.radius: extra spacing for the fan arc. Defaults to1.
MenuPreset
MenuPreset defines dropdown anchor and direction combinations. Center, edge,
corner, and bidirectional presets are available.
FanMenuPreset
FanMenuPreset defines circular and half-curve radial menu arrangements.
Performance Notes
Menu Kit uses Flutter Flow and FlowDelegate, so item positions are painted
efficiently during animation without rebuilding every child for every frame.
For best results:
- Reuse one
AnimationControllerper menu instance. - Keep menu children lightweight and prefer const widgets where possible.
- Use stable
heroTagvalues forFloatingActionButtonchildren. - Dispose controllers in the owning state object.
License
Menu Kit is available under the MIT License. See LICENSE.
Libraries
- Animated dropdown and fan menus for Flutter.











