Pull Tab Menu Icon

platform pub package pub points documentation interactive demo last updated by

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),
);

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).

Libraries

pull_tab_menu