Fluid Side Menu

Pub Version Pub Likes Platform License: BSD 3-Clause

A premium, highly-customizable fluid side navigation drawer for Flutter. It features an organic, gooey liquid-reveal transition (using high-performance custom vector splines), staggered menu option entrance animations, and rich selection feedback behaviors.


Table of Contents


Why Fluid Side Menu?

While standard side drawers transition rigidly across the screen, Fluid Side Menu uses organic motion curves and wavy vector splines to deliver a fluid, high-fidelity navigational experience.

Key benefits include:

  • No Edge Pixelation: The custom waves are drawn dynamically as sharp vector paths, avoiding the pixelation or fuzzy edges common with raster masks.
  • Optimized Performance: Leverages isolated RepaintBoundary nodes and linear animation inputs to run smoothly at 60fps/120fps even on lower-end devices.
  • Custom Easing Curves: The fluid wave transition supports custom animation curves, allowing you to tailor the physics of the goo transition (e.g. springy elastic waves, snappy deceleration, or bounce reveals).

Features

  • Organic Liquid Transition: High-performance transition using custom vector wave splines that merge and expand across the screen.
  • Staggered Option Animations: Smooth, delayed entrance animations for menu items (including fade, scale, or springy slide-up) to establish visual hierarchy.
  • Rich Selection Feedback: A collection of interactive tap animations, including the Icon Slide Swap (where the text fades out and collapses, sliding the selected icon directly into the horizontal center).
  • Item-Level Customization: Control background colors, gradients, text styles, spacings, and override individual menu item colors (text and icons) independently.

Getting started

Add fluid_side_menu to your pubspec.yaml dependencies:

dependencies:
  fluid_side_menu: ^1.0.0

Then, import the package in your Dart code:

import 'package:fluid_side_menu/fluid_side_menu.dart';

Usage

Standard Setup

Here is how you can implement FluidSideMenu in a standard Flutter application using stateless widgets for pages:

import 'package:flutter/material.dart';
import 'package:fluid_side_menu/fluid_side_menu.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Fluid Side Menu Demo',
      theme: ThemeData(useMaterial3: true),
      home: const DemoScreen(),
    );
  }
}

class DemoScreen extends StatefulWidget {
  const DemoScreen({super.key});

  @override
  State<DemoScreen> createState() => _DemoScreenState();
}

class _DemoScreenState extends State<DemoScreen> {
  @override
  Widget build(BuildContext context) {
    // Define the menu items pointing to actual widget screens
    final List<FluidMenuItem> items = [
      FluidMenuItem(
        label: 'Home',
        page: const HomeScreen(),
        icon: const Icon(Icons.home),
      ),
      FluidMenuItem(
        label: 'Categories',
        page: const CategoriesScreen(),
        icon: const Icon(Icons.category),
      ),
      FluidMenuItem(
        label: 'About',
        page: const AboutScreen(),
        icon: const Icon(Icons.info),
      ),
      FluidMenuItem(
        label: 'Contact us',
        page: const ContactScreen(),
        icon: const Icon(Icons.mail),
        // Item-level color customizations override the global defaults
        textColor: Colors.orangeAccent,
        iconColor: Colors.orangeAccent,
      ),
    ];

    return Scaffold(
      body: FluidSideMenu(
        fluidColor: Colors.black, // Background color of the reveal drawer
        duration: const Duration(milliseconds: 700), // Speed of wave
        showBuiltInButtons: true, // Auto-renders menu and close buttons
        menuAnimationType: FluidMenuAnimationType.slide,
        selectAnimationType: FluidMenuSelectAnimationType.iconSlideSwap,
        menuItems: items,
      ),
    );
  }
}

// Simple StatelessWidgets representing target screens:
class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});
  @override
  Widget build(BuildContext context) => const Scaffold(body: Center(child: Text('Home Page')));
}

class CategoriesScreen extends StatelessWidget {
  const CategoriesScreen({super.key});
  @override
  Widget build(BuildContext context) => const Scaffold(body: Center(child: Text('Categories Page')));
}

class AboutScreen extends StatelessWidget {
  const AboutScreen({super.key});
  @override
  Widget build(BuildContext context) => const Scaffold(body: Center(child: Text('About Page')));
}

class ContactScreen extends StatelessWidget {
  const ContactScreen({super.key});
  @override
  Widget build(BuildContext context) => const Scaffold(body: Center(child: Text('Contact Page')));
}

Programmatic Control

To open, close, or toggle the drawer programmatically from any screen widget placed inside the side menu, use the static FluidSideMenu.of(context) helper:

// Open the side menu
FluidSideMenu.of(context)?.open();

// Close the side menu
FluidSideMenu.of(context)?.close();

// Toggle the side menu
FluidSideMenu.of(context)?.toggle();

Alternatively, you can assign a GlobalKey<FluidSideMenuState> to the FluidSideMenu widget and call key.currentState?.open().

Customizing the Reveal Background

Instead of a solid color, you can pass a LinearGradient or RadialGradient to create a custom gradient appearance for the gooey wave:

FluidSideMenu(
  menuItems: items,
  fluidGradient: const LinearGradient(
    colors: [
      Color(0xFF0F0C20), // Dark indigo-black
      Color(0xFF15102A), // Dark violet
      Color(0xFF06040A), // Deep black
    ],
    begin: Alignment.topLeft,
    end: Alignment.bottomRight,
  ),
  // ... other parameters
)

API Reference

FluidSideMenu Options

Parameter Type Default Description
menuItems List<FluidMenuItem> Required The navigation screens, labels, and icons.
child Widget? null Optional static override for the main screen (if not relying on the menu item pages).
fluidColor Color Colors.black The background color of the reveal wave drawer.
fluidGradient Gradient? null Gradient override for the reveal wave background.
duration Duration Duration(milliseconds: 650) Length of the opening and closing transitions.
animationCurve Curve Curves.easeInOutCubic Easing curve for the fluid transition.
showBuiltInButtons bool true Auto-renders the top-left menu open button and top-right close toggle button.
menuIcon Widget? null Custom icon widget for the main menu open toggle button.
closeIcon Widget? null Custom icon widget for the close toggle button.
buttonRadius double 20.0 Initial circle radius of the menu toggle button.
menuAnimationType FluidMenuAnimationType FluidMenuAnimationType.slide Entry transition type for options (fade, scale, slide).
selectAnimationType FluidMenuSelectAnimationType FluidMenuSelectAnimationType.scalePulse Tapped selection feedback style (iconSlideSwap, scalePulse, etc.).
menuItemTextStyle TextStyle? null Text styling of option labels.
menuItemTextColor Color? null Default text color fallback for all items (if not set in FluidMenuItem).
menuItemIconColor Color? null Default icon color fallback for all items (if not set in FluidMenuItem).
menuItemSpacing double 12.0 Spacing between option icons and text labels.

FluidMenuItem Options

Parameter Type Default Description
label String Required Label text displayed for the option.
page Widget Required Target page screen widget to show when tapped.
icon Widget? null Prefix icon widget.
textColor Color? null Individual custom override for the label text color.
iconColor Color? null Individual custom override for the prefix icon color.

Selection Feedback Animations

Value Behavior
iconSlideSwap Selected item's label fades/slides out, collapsing size to let the icon center horizontally. Others fade to 0.25 opacity.
scalePulse Selected item scales up to 1.08, others dim to 0.35 opacity.
slideRight Selected item slides right, others dim to 0.35 opacity.
scaleDownOthers Selected item stays stable, others scale down to 0.9 and dim.
fadeOthers Selected item stays stable, others dim.
none Immediate nav execution without feedback animation.

Additional information

Source Code and Contributions

The source code and examples are hosted on GitHub. If you wish to contribute, report bugs, or request features, please open an issue or pull request in the repository.

Reporting Issues

Please use the repository's GitHub Issues page to report bugs, request documentation updates, or propose new design features.

License

This project is licensed under the BSD 3-Clause License - see the LICENSE file for details.

Libraries

fluid_side_menu