staggered_menu_flutter

A premium staggered slide-in navigation menu for Flutter.
Animated pre-layers ยท Backdrop blur glass panel ยท Hover effects ยท Fully themeable.

pub version pub points license: MIT GitHub Flutter Dart


โœจ Features

Feature Details
๐ŸŽž Staggered layers Multiple coloured sheets slide in behind the glass panel, each offset in time
๐ŸŒซ Backdrop blur panel Frosted-glass panel with configurable blur sigma and tint opacity
๐Ÿ–ฑ Hover effects Item and social-link hover states (colour + opacity) โ€” perfect for web & desktop
๐Ÿ”ข Item numbering Optional two-digit ordinals that fade in with each menu item
๐ŸŽจ Deep theming Every colour, font, spacing, and motion curve is configurable via StaggeredMenuThemeData
๐Ÿ“ฑ Responsive Full-width panel on mobile, clamped fractional width on larger screens
โ™ฟ Accessible Semantics labels on all interactive elements
๐Ÿ”€ Left / right Panel can slide in from either edge
๐Ÿ’ฌ Socials section Optional footer row with hover-dimming spotlight effect
๐ŸŽฎ Controller StaggeredMenuController for programmatic open / close / toggle
๐ŸŽจ Inherited theme StaggeredMenuTheme InheritedWidget โ€” set once, inherit everywhere
๐Ÿ›ค Route helper StaggeredRouteHelper.fromRoutes() maps named routes to menu items automatically
๐Ÿงฉ Custom item builder itemBuilder slot for fully custom per-item rendering while keeping stagger animation
โŒจ๏ธ Keyboard nav Focus trap when open โ€” Escape closes the menu

๐Ÿš€ Getting started

Add to your pubspec.yaml:

dependencies:
  staggered_menu_flutter: ^0.0.3

Then run:

flutter pub get

๐Ÿ”จ Usage

Minimal

import 'package:staggered_menu_flutter/staggered_menu_flutter.dart';

StaggeredMenu(
  items: [
    StaggeredMenuItem(label: 'Home',    onTap: () {}),
    StaggeredMenuItem(label: 'About',   onTap: () {}),
    StaggeredMenuItem(label: 'Contact', onTap: () {}),
  ],
  child: Scaffold(
    body: Center(child: Text('My App')),
  ),
)

With all options

StaggeredMenu(
  position: MenuPosition.right,   // or MenuPosition.left
  theme: StaggeredMenuThemeData(
    accentColor:      Color(0xFFFF2D55),
    preLayerColors:   [Color(0xFFFFC2D1), Color(0xFFFF2D55)],
    panelColor:       Colors.white,
    panelOpacity:     0.93,
    blurSigma:        16,
    barrierColor:     Color(0x44000000),
    showItemNumbering: true,
    enableHoverEffects: true,
    duration:         Duration(milliseconds: 800),
    panelCurve:       Curves.easeOutQuart,
  ),
  logo: Text(
    'STUDIO',
    style: TextStyle(color: Colors.white, fontWeight: FontWeight.w800),
  ),
  items: [
    StaggeredMenuItem(label: 'Home',     onTap: () {}),
    StaggeredMenuItem(label: 'Work',     onTap: () {}),
    StaggeredMenuItem(label: 'About',    onTap: () {}),
    StaggeredMenuItem(label: 'Contact',  onTap: () {}),
  ],
  socialItems: [
    StaggeredSocialItem(label: 'GitHub',   onTap: () {}),
    StaggeredSocialItem(label: 'Dribbble', onTap: () {}),
    StaggeredSocialItem(label: 'X',        onTap: () {}),
  ],
  onMenuOpen:  () => print('opened'),
  onMenuClose: () => print('closed'),
  child: Scaffold(
    backgroundColor: Color(0xFF0E0E12),
    body: Center(child: Text('Hello')),
  ),
)

๏ฟฝ Controller

Open, close, or toggle the menu from code:

final controller = StaggeredMenuController();

StaggeredMenu(
  controller: controller,
  items: [ /* โ€ฆ */ ],
  child: myScaffold,
);

// Later:
controller.open();
controller.close();
controller.toggle();

// Dispose when done:
controller.dispose();

๐ŸŽจ Inherited theme

Wrap a subtree with StaggeredMenuTheme to avoid passing theme: to every menu:

StaggeredMenuTheme(
  data: StaggeredMenuThemeData(accentColor: Colors.red),
  child: MaterialApp(home: MyPage()),
)

Resolution order: explicit theme parameter โ†’ nearest StaggeredMenuTheme โ†’ built-in defaults.


๐Ÿ›ค Named routes integration

StaggeredMenu(
  items: StaggeredRouteHelper.fromRoutes(
    context,
    routes: {
      '/':        'Home',
      '/about':   'About',
      '/contact': 'Contact',
    },
    currentRoute: ModalRoute.of(context)?.settings.name,
  ),
  child: myScaffold,
)

The active route automatically gets a null onTap (disabled).


๐Ÿงฉ Custom item builder

Replace the default uppercase-label rendering while keeping the stagger animation:

StaggeredMenu(
  itemBuilder: (context, item, index, hovered) {
    return Text(
      item.label,
      style: TextStyle(color: hovered ? Colors.red : Colors.white),
    );
  },
  items: [ /* โ€ฆ */ ],
  child: myScaffold,
)

โŒจ๏ธ Keyboard navigation

When the menu overlay is open:

  • A FocusScope traps focus within the panel.
  • Pressing Escape closes the menu.

No extra setup required โ€” it works out of the box.


๏ฟฝ๐ŸŽจ Theming reference

All properties have sensible defaults โ€” override only what you need using copyWith:

const StaggeredMenuThemeData().copyWith(
  accentColor: Colors.deepPurple,
  blurSigma:   20,
  duration:    Duration(milliseconds: 600),
)
Full property list
Property Type Default Description
preLayerColors List<Color> purple tones Decorative layers behind the panel
panelColor Color white Panel base fill colour
panelOpacity double 0.95 Panel fill alpha (0โ€“1)
blurSigma double 12 Backdrop blur std-dev
accentColor Color #5227FF Numbers, hover, social title
toggleColorClosed Color white Toggle icon colour when closed
toggleColorOpen Color black Toggle icon colour when open
toggleIconSize double 22 Size of the + icon
toggleRotationDegrees double 225 Rotation of the + on open
headerPadding EdgeInsets h24 v20 Padding around logo + toggle row
panelPadding EdgeInsets custom Inner panel padding
panelMinWidth double 260 Minimum panel width (px)
panelMaxWidth double 420 Maximum panel width (px)
panelWidthFraction double 0.38 Panel width as screen fraction
mobileBreakpoint double 640 Full-width panel below this width
closeOnClickAway bool true Close when tapping the barrier
barrierColor Color transparent Scrim behind the panel
itemTextStyle TextStyle bold 48px Menu item text
itemHoverTextStyle TextStyle bold 48px accent Menu item hover text
numberTextStyle TextStyle bold 13px accent Ordinal numbers
socialsTitleStyle TextStyle semi 14px "Socials" heading
socialLinkStyle TextStyle semi 16px Social link text
socialLinkHoverStyle TextStyle semi 16px accent Social link hover
showItemNumbering bool true Show two-digit ordinals
enableHoverEffects bool true Enable mouse-over interactions
duration Duration 900 ms Total open/close duration
panelCurve Curve easeOutQuart Panel slide curve
layerCurve Curve easeOutQuart Pre-layer slide curve
itemCurve Curve easeOutQuart Item entrance curve
layerStagger double 0.08 Normalised delay between layers
itemStagger double 0.07 Normalised delay between items

๐Ÿ“ Package structure

staggered_menu_flutter/
โ”œโ”€โ”€ lib/
โ”‚   โ”œโ”€โ”€ staggered_menu_flutter.dart   โ† public barrel (import this)
โ”‚   โ””โ”€โ”€ src/
โ”‚       โ”œโ”€โ”€ controller.dart           โ† StaggeredMenuController
โ”‚       โ”œโ”€โ”€ menu_theme.dart           โ† StaggeredMenuTheme (InheritedWidget)
โ”‚       โ”œโ”€โ”€ models.dart               โ† StaggeredMenuItem, StaggeredSocialItem, MenuPosition
โ”‚       โ”œโ”€โ”€ route_helper.dart         โ† StaggeredRouteHelper
โ”‚       โ”œโ”€โ”€ theme.dart                โ† StaggeredMenuThemeData
โ”‚       โ””โ”€โ”€ staggered_menu.dart       โ† StaggeredMenu widget + itemBuilder + keyboard nav
โ”œโ”€โ”€ example/
โ”‚   โ””โ”€โ”€ lib/main.dart                 โ† runnable demo
โ”œโ”€โ”€ test/
โ”‚   โ””โ”€โ”€ staggered_menu_flutter_test.dart  (33 tests)
โ”œโ”€โ”€ CHANGELOG.md
โ”œโ”€โ”€ LICENSE
โ””โ”€โ”€ pubspec.yaml

๐Ÿงช Running tests

flutter test

๐Ÿ—บ Roadmap

  • x StaggeredMenuController for programmatic open/close
  • x Named routes integration helper (StaggeredRouteHelper)
  • x StaggeredMenuTheme inherited widget
  • x Custom item builder slot (itemBuilder)
  • x Keyboard navigation (focus trap + Escape)

Upcoming:

  • RTL layout support
  • Spring physics animation preset
  • Built-in hero transition for page changes

๐Ÿค Contributing

PRs and issues are welcome at github.com/NexivaServices/staggered_menu_flutter!
Please open an issue before submitting a large change so we can discuss the approach.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feat/my-feature)
  3. Commit your changes (git commit -m 'feat: add my feature')
  4. Push to the branch (git push origin feat/my-feature)
  5. Open a Pull Request

๐Ÿ“„ License

MIT ยฉ 2026 โ€” see LICENSE for details.

Libraries

staggered_menu_flutter
A staggered sliding navigation menu for Flutter.