Flutter's star_menu Package: Creating Beautiful Context Menus
FlutterPulseThis article was translated specially for the channel FlutterPulseYou'll find lots of interesting things related to Flutter on this channel. Don't hesitate to subscribe!🚀

Flutter's default popup menu looks boring. It's just a rectangle with items inside. Not very exciting, right?

That's where the star_menu package comes to help. This package lets you create fancy popup menus with different shapes and smooth animations.

If you are a member, please continue,otherwise, read the full story here.
Content
What makes star_menu specialGetting startedBasic implementationWorking with Different Shapes
∘ Linear Shape
∘ Circle Shape
∘ Grid ShapeAdding AnimationsHandling User InteractionsSubMenusAdvanced Features
∘ Lazy Loading Items
∘ Background EffectsFull code on GitHub
What makes star_menu special
The star_menu is a contextual popup menu with different shapes and multiple ways to fine-tune animation and position. You can use almost any widget as a menu entry.
The package gives you three main shapes to work with. Linear shape puts items in straight line. Circle shape arranges them in circle. Grid shape creates neat rows and columns.
Each shape has its own use case. Linear works great for simple menus. Circle looks fancy for special buttons. Grid is perfect when you have many options.
Getting started
First, add the package to your project:
dependencies:
star_menu: ^4.0.1
Then run flutter pub get and you're ready to go.
Using the package is pretty simple. You need three main things: menu items, parameters, and a child widget.
Basic implementation
Here's simplest way to create star menu:
StarMenu(
params: StarMenuParameters(),
items: [
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.blue,
shape: BoxShape.circle,
),
child: Icon(Icons.home, color: Colors.white),
),
Container(
width: 40,
height: 40,
decoration: BoxDecoration(
color: Colors.red,
shape: BoxShape.circle,
),
child: Icon(Icons.search, color: Colors.white),
),
],
child: FloatingActionButton(
onPressed: () {},
child: Icon(Icons.menu),
),
)
This creates a circular menu with two items. When user taps the floating button, menu opens with smooth animation.
Any widget can be an item.
Working with Different Shapes
Linear Shape
Linear shape is most straightforward. Items line up in straight line:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.linear,
linearShapeParams: LinearShapeParams(
angle: 90, // vertical line
space: 10, // space between items
alignment: LinearAlignment.center,
),
),
items: menuItems,
child: yourTriggerWidget,
)
You can change angleto make a line horizontal, diagonal, or any direction you want. Space parameter controls the distance between items.

Circle Shape
The circle shape looks most impressive. Items are arranged in a perfect circle around the trigger:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.circle,
circleShapeParams: CircleShapeParams(
radiusX: 120,
radiusY: 120,
startAngle: 0,
endAngle: 360,
),
),
items: menuItems,
child: yourTriggerWidget,
)
You can make oval shapes by using different radiusXand radiusYvalues. StartAngleand endAnglelet you create partial circles.

Grid Shape
Grid shape works best for many menu items:
StarMenu(
params: StarMenuParameters(
shape: MenuShape.grid,
gridShapeParams: GridShapeParams(
columns: 3,
columnsSpaceH: 15,
columnsSpaceV: 15,
),
),
items: menuItems,
child: yourTriggerWidget,
)
This creates 3-column grid with 15 pixels spacing. Perfect for app launcher or tool palette.

Adding Animations
Animations make menus feel alive. You can control several animation aspects:
StarMenuParameters(
openDurationMs: 600,
closeDurationMs: 200,
rotateItemsAnimationAngle: 45,
startItemScaleAnimation: 0.1,
animationCurve: Curves.bounceOut,
)
Items can rotate while appearing. They can start small and grow to full size. Different curves create different feels.

Handling User Interactions
You want to know when user taps menu items:
StarMenu(
params: StarMenuParameters(),
items: menuItems,
onItemTapped: (index, controller) {
print('User tapped item $index');
// Close menu after selection
controller.closeMenu();
// Handle the action
switch (index) {
case 0:
navigateToHome();
break;
case 1:
openSearch();
break;
}
},
child: triggerWidget,
)
The callback gives you the item index and controller. Controller lets you close the menu programmatically.
SubMenus
The Star Menu can be added to any widget. Thus, we can create the menu with items and then add the Star Menu to every item, and so on, resulting in a menu with submenus of any depth.
static List<Widget> buildAnimatedMenuItems() {
return [
_buildCircularItem(Icons.home, Colors.deepPurple),
_buildCircularItem(Icons.search, Colors.deepPurple),
_buildCircularItem(Icons.settings, Colors.deepPurple),
_buildCircularItem(Icons.favorite, Colors.deepPurple).addStarMenu(
items: subMenuEntries(),
params: const StarMenuParameters(
shape: MenuShape.linear,
linearShapeParams: LinearShapeParams(
angle: 120,
space: 15,
),
checkMenuScreenBoundaries: true,
),
),
];
}Note that there is an extension method that can be used instead of the StarMenuconstructor.

Advanced Features
Lazy Loading Items
Sometimes you need to build menu items dynamically:
StarMenu(
params: StarMenuParameters(),
lazyItems: () async {
// Simulate API call
await Future.delayed(Duration(milliseconds: 200));
return [
buildDynamicItem('New Item 1'),
buildDynamicItem('New Item 2'),
];
},
child: triggerWidget,
)
This is useful when menu content depends on user data or API responses.

Background Effects
Make menu more attractive with background blur:
StarMenuParameters(
backgroundParams: BackgroundParams(
animatedBlur: true,
sigmaX: 5.0,
sigmaY: 5.0,
animatedBackgroundColor: true,
backgroundColor: Colors.black.withValues(alpha: 0.3),
),
)
This creates a blurred background that fades in smoothly.

Full code on GitHub
To not overfill the story with code, the above code snippets contain only essential code parts.
The full code of my demo is here (GetX).
The official package examples are here.
Happy coding!
