Pull Tab Menu 
Elegant context menus for Flutter apps via a discreet pull-out tab. Preserves clean aesthetics while providing quick access to actions.
Try it out in the demo app.
![]() |
![]() |
![]() |
---|
Features
- Edge-anchored pull tab with customizable appearance
- Multiple initial menu positions (centerLeft, centerRight, topLeft, topRight, bottomLeft, bottomRight)
- Slide-out menu with smooth animations
- Support for both vertical and horizontal menu layouts
- Menu items with icons, tooltips, and tap actions
- Built-in divider support
- Material Design 3 theme integration
- Auto-hide functionality with configurable delay
- Configurable animations (duration and curves)
- Gesture-based interactions (tap, swipe, drag)
- Hover interactions for desktop/web platforms
- Optional background overlay
- Smart automatic layout selection based on item count
- Programmatic control via controller
- Customizable colors, opacity, and dimensions
Usage
Basic Usage
import 'package:flutter/material.dart';
import 'package:pull_tab_menu/pull_tab_menu.dart';
// Basic example of using a pull tab menu
Scaffold buildBasicExample(BuildContext context) {
// Create menu items
final menuItems = [
PullTabMenuItem(
label: 'Home',
icon: Icons.home,
onTap: () {
// Handle tap action
},
),
PullTabMenuItem(
label: 'Settings',
icon: Icons.settings,
onTap: () {
// Handle tap action
},
),
PullTabMenuItem(
label: 'Profile',
icon: Icons.person,
onTap: () {
// Handle tap action
},
),
];
return Scaffold(
appBar: AppBar(
title: const Text('Pull Tab Menu Demo'),
),
body: PullTabMenu(
menuItems: menuItems,
child: const Center(
child: Text('Pull from the right edge to open the menu'),
),
),
);
}
Using a Controller for Programmatic Control
class _MyHomePageState extends State<MyHomePage> {
final PullTabController _controller = PullTabController();
@override
void initState() {
super.initState();
// Demonstrate opening/closing the menu programmatically
// Give the user a quick peek of the menu to show they can open/close it
Future.delayed(Durations.short2, () => _controller.openMenu()).then(
(value) => Future.delayed(Durations.long2, () => _controller.closeMenu()),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Pull Tab Menu Examples')),
body: PullTabMenu(
controller: _controller,
menuItems: [
PullTabMenuItem(
label: 'Example 1',
icon: Icons.draw,
onTap: () {
// Handle navigation
Navigator.pushNamed(context, '/example1');
},
),
PullTabMenuItem(
label: 'Example 2',
icon: Icons.style_outlined,
onTap: () {
// Handle navigation
Navigator.pushNamed(context, '/example2');
},
),
],
child: Center(
child: MaterialButton(
child: Text('Open Menu'),
onPressed: () {
// Open the menu
_controller.openMenu();
},
),
),
),
);
}
}
Customization Options
The PullTabMenuConfiguration
class provides extensive customization options:
PullTabMenuConfiguration(
// Menu Alignment
initialAlignment: MenuAlignment.centerRight,
allowRepositioning: true,
// Layout
axis: Axis.vertical,
margin: 8.0,
borderRadius: 8.0,
itemExtent: 48.0,
menuBreadth: 60.0,
// Tab Size
tabWidth: 40.0,
tabHeight: 80.0,
// Colors
baseColor: null, // Defaults to theme's inverseSurface
tabColor: null, // Defaults to the base color
foregroundColor: null, // Defaults to theme's onInverseSurface
selectedItemBorderColor: null, // Defaults to the foreground color
selectedItemBackgroundColor: null, // Defaults to the base color
// Divider Appearance
dividerThickness: 0.5,
dividerIndent: 8.0,
// Opacity
tabOpacity: 0.7,
menuOpacity: 1.0,
useBackgroundOverlay: true,
backgroundOverlayOpacity: 0.5,
// Animation
showDuration: Duration(milliseconds: 250),
showCurve: Curves.easeInOut,
hideDuration: Duration(milliseconds: 250),
hideCurve: Curves.easeInOut,
// Behavior
openOnTabHover: false,
closeMenuOnTap: true,
autoHide: false,
autoHideDelay: Duration(seconds: 3),
);
Menu Alignments
The initial menu can be positioned at various points along the screen edges:
MenuAlignment.topLeft
MenuAlignment.centerLeft
MenuAlignment.bottomLeft
MenuAlignment.topRight
MenuAlignment.centerRight
MenuAlignment.bottomRight
Auto Layout
The menu will automatically choose between vertical and horizontal layouts based on the number of items, unless overridden:
- For 3 or fewer items: Horizontal layout
- For 4 or more items: Vertical layout
You can explicitly set the axis
parameter to override this behavior.
Theme Integration
The menu automatically integrates with Material Design 3 theme colors:
- Base color defaults to
colorScheme.inverseSurface
- Foreground color defaults to
colorScheme.onInverseSurface
This provides a nice contrast with your app's primary colors while maintaining theme consistency.
Dividers
You can add dividers to your menu to visually separate groups of items:
final menuItems = [
PullTabMenuItem(label: 'Logout', icon: Icons.logout),
PullTabMenuItem.divider(), // Add a divider
PullTabMenuItem(label: 'Home', icon: Icons.home),
PullTabMenuItem(label: 'Profile', icon: Icons.person),
PullTabMenuItem(label: 'Settings', icon: Icons.settings),
];
Dividers automatically adapt to the menu orientation (horizontal or vertical).