Animated Menu
A professional Flutter package for creating beautiful, animated popup menus with smooth corners, backdrop blur, and customizable animations. Zero external dependencies - everything is built-in.

Features
- Smooth Corners: iOS/macOS-style continuous corners (squircle)
- Backdrop Blur: Beautiful blur effect behind the menu
- Built-in Animations: Multiple animation presets (fade, scale, bounce, elastic, slide, etc.)
- Theme Support: Dark/light presets and full customization
- Rich Menu Items: Icons, keyboard shortcuts, destructive actions
- Multiple APIs: Function-based, widget-based, and extension methods
- Zero Dependencies: No external packages required
Installation
Add animated_menu to your pubspec.yaml:
dependencies:
animated_menu: ^1.0.3
Quick Start
import 'package:animated_menu/animated_menu.dart';
// Show menu on tap
GestureDetector(
onTapDown: (details) {
showAnimatedMenu(
context: context,
position: details.globalPosition,
menu: AnimatedMenu(
items: [
AnimatedMenuButtonItem(
icon: Icons.copy,
child: Text('Copy'),
onSelected: () => print('Copy!'),
),
AnimatedMenuDivider(),
AnimatedMenuButtonItem(
icon: Icons.delete,
child: Text('Delete'),
isDestructive: true,
onSelected: () => print('Delete!'),
),
],
),
);
},
child: YourWidget(),
)
Usage Examples
Basic Menu
showAnimatedMenu(
context: context,
position: tapPosition,
menu: AnimatedMenu(
items: [
AnimatedMenuButtonItem(
icon: Icons.edit,
child: Text('Edit'),
onSelected: () => handleEdit(),
),
AnimatedMenuButtonItem(
icon: Icons.share,
child: Text('Share'),
onSelected: () => handleShare(),
),
],
),
);
With Animation Presets
showAnimatedMenu(
context: context,
position: position,
animationConfig: MenuAnimationConfig.bounceIn, // or .elasticIn, .scale, .fadeIn
menu: AnimatedMenu(
items: [...],
),
);
With Theme
AnimatedMenu(
theme: AnimatedMenuTheme.dark, // or .light
items: [...],
)
Custom Theme
AnimatedMenu(
theme: AnimatedMenuTheme(
backgroundColor: Colors.grey[900],
hoverColor: Colors.grey[800],
textStyle: TextStyle(color: Colors.white),
iconColor: Colors.white70,
),
items: [...],
)
With Section Headers
AnimatedMenu(
items: [
AnimatedMenuHeader(title: 'Actions'),
AnimatedMenuButtonItem(
icon: Icons.copy,
child: Text('Copy'),
trailing: Text('⌘C'),
onSelected: () {},
),
AnimatedMenuButtonItem(
icon: Icons.paste,
child: Text('Paste'),
trailing: Text('⌘V'),
onSelected: () {},
),
AnimatedMenuDivider(),
AnimatedMenuHeader(title: 'Danger Zone'),
AnimatedMenuButtonItem(
icon: Icons.delete,
child: Text('Delete'),
isDestructive: true,
onSelected: () {},
),
],
)
Using AnimatedMenuAnchor Widget
AnimatedMenuAnchor(
menuBuilder: (context) => AnimatedMenu(
items: [
AnimatedMenuButtonItem(
child: Text('Option 1'),
onSelected: () {},
),
],
),
child: ElevatedButton(
onPressed: null,
child: Text('Show Menu'),
),
)
Using AnimatedMenuButton (for App Bars)
AppBar(
actions: [
AnimatedMenuButton(
icon: Icons.more_vert,
menuBuilder: (context) => AnimatedMenu(
theme: AnimatedMenuTheme.dark,
items: [
AnimatedMenuButtonItem(
icon: Icons.settings,
child: Text('Settings'),
onSelected: () {},
),
],
),
),
],
)
Using Extension Method
MyWidget().withAnimatedMenu(
menuBuilder: (context) => AnimatedMenu(
items: [...],
),
)
Using AnimatedMenuController
final menuController = AnimatedMenuController();
// Show menu
menuController.show(
context: context,
position: tapPosition,
menu: AnimatedMenu(items: [...]),
);
// Dismiss programmatically
menuController.dismiss();
Animation Presets
| Preset | Description |
|---|---|
MenuAnimationConfig.none |
No animation |
MenuAnimationConfig.fadeIn |
Simple fade in |
MenuAnimationConfig.scale |
Scale up with easeOutBack |
MenuAnimationConfig.fadeScale |
Fade + scale (default) |
MenuAnimationConfig.bounceIn |
Bouncy entrance |
MenuAnimationConfig.elasticIn |
Elastic spring effect |
MenuAnimationConfig.slideDown |
Slide from top |
MenuAnimationConfig.slideUp |
Slide from bottom |
MenuAnimationConfig.zoomIn |
Zoom with overshoot |
Custom Animation
MenuAnimationConfig(
animation: MenuAnimation.fadeScale,
duration: Duration(milliseconds: 250),
curve: Curves.easeOutBack,
initialScale: 0.8,
)
Menu Item Types
| Widget | Description |
|---|---|
AnimatedMenuButtonItem |
Clickable item with text, icons |
AnimatedMenuDivider |
Visual separator |
AnimatedMenuHeader |
Section header text |
AnimatedMenuCustomItem |
Custom content |
AnimatedMenu Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
items |
List<AnimatedMenuEntity> |
required | Menu items |
width |
double? |
null | Fixed width |
minWidth |
double? |
120 | Minimum width |
maxWidth |
double? |
320 | Maximum width |
borderRadius |
double |
12 | Corner radius |
cornerSmoothing |
double |
0.6 | Squircle smoothing (0-1) |
blurSigma |
double |
20 | Backdrop blur amount |
enableBlur |
bool |
true | Enable blur effect |
theme |
AnimatedMenuTheme? |
null | Theme configuration |
animationConfig |
MenuAnimationConfig |
default | Menu animation |
itemAnimationConfig |
MenuItemAnimationConfig |
none | Item animations |
AnimatedMenuButtonItem Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
child |
Widget |
required | Item content |
onSelected |
VoidCallback? |
null | Selection callback |
icon |
IconData? |
null | Leading icon |
trailingIcon |
IconData? |
null | Trailing icon |
trailing |
Widget? |
null | Trailing widget |
isDestructive |
bool |
false | Red destructive style |
height |
double |
44 | Item height |
Migration from 1.0.2
The animate_do package is no longer required. Replace:
// Old (1.0.2)
FadeIn(
child: AnimatedMenuButtonItem(...),
)
// New (1.0.3)
AnimatedMenu(
animationConfig: MenuAnimationConfig.fadeIn,
items: [
AnimatedMenuButtonItem(...),
],
)
The preferredAnchorPoint parameter is now position (old name still works).
License
MIT License - see LICENSE for details.
Libraries
- A professional Flutter package for creating beautiful, animated popup menus with smooth corners, backdrop blur, and customizable animations.