liquid_tab_bar 2.0.0 copy "liquid_tab_bar: ^2.0.0" to clipboard
liquid_tab_bar: ^2.0.0 copied to clipboard

An iOS 26-style floating liquid-glass tab bar for Flutter with a deformable droplet, refraction, search, actions, badges, and scroll-aware folding.

liquid_tab_bar #

A floating glass tab bar for Flutter. It supports a moving selection lens, search, action buttons, badges, and a compact shape while scrolling.

Package version in this repository: 2.0.0

pub version 2.0.0 license


iOS simulator preview #

Current normal styles on an iPhone 17 Pro Max simulator. Both images show the same tab bar with a selected tab and a notification badge.

Light Dark
Normal light LiquidTabBar on iOS Normal dark LiquidTabBar on iOS

Features #

  • Animated selection: Tap or drag across tabs; the glass lens follows and settles on the selected tab.
  • Glass with fallbacks: Uses shader glass where supported, backdrop blur elsewhere, and an opaque mode when needed.
  • Search and actions: Add an expandable search field or a separate action button beside the tabs.
  • Icons and badges: Use Flutter icons or your own widgets, plus unread dots, counts, or text badges.
  • Scroll folding: The bar can shrink to a small pill while you scroll and expand again when you return.
  • Accessibility: Supports screen readers, right-to-left layouts, and reduced motion settings.

Installation #

For a published 2.0.0 release, add this to your app's pubspec.yaml:

dependencies:
  liquid_tab_bar: ^2.0.0

To try this repository before that version is published, use a local path instead. Adjust the path to where you cloned this repository:

dependencies:
  liquid_tab_bar:
    path: ../liquid_tab_bar

Then run flutter pub get. Import the package in your Dart file:

import 'package:liquid_tab_bar/liquid_tab_bar.dart';

The glass shaders are bundled with the package. Your app does not need to declare them as assets.

Note

SVG support is optional. If you use SVG icons, add an SVG package such as flutter_svg to your app. Standard Flutter icons work without it.

Quick Start #

This complete lib/main.dart example shows three tabs and a scrollable page:

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

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await LiquidGlass.load();
  runApp(const DemoApp());
}

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

  @override
  State<DemoApp> createState() => _DemoAppState();
}

class _DemoAppState extends State<DemoApp> {
  int selectedIndex = 0;

  @override
  Widget build(BuildContext context) {
    const tabLabels = ['Home', 'Explore', 'Profile'];
    return MaterialApp(
      home: LiquidTabBarScaffold(
        appBar: AppBar(title: const Text('Liquid Tab Bar')),
        body: ListView.builder(
          itemCount: 30,
          itemBuilder: (context, index) => ListTile(
            title: Text('${tabLabels[selectedIndex]} item ${index + 1}'),
          ),
        ),
        tabBar: LiquidTabBar(
          selectedIndex: selectedIndex,
          onSelected: (index) => setState(() => selectedIndex = index),
          items: const [
            LiquidTabItem.icon(label: 'Home', icon: Icons.home_outlined),
            LiquidTabItem.icon(label: 'Explore', icon: Icons.explore_outlined),
            LiquidTabItem.icon(label: 'Profile', icon: Icons.person_outline),
          ],
        ),
      ),
    );
  }
}

Save the file and run flutter run.

selectedIndex tells the bar which tab is active. onSelected updates your app state when the user chooses a tab. Replace the sample ListView with your own content. LiquidTabBarScaffold lets the page draw behind the floating bar, adds bottom space so the last list item stays visible, and handles scroll folding. LiquidGlass.load() prepares the shader; the bar falls back to blur when shader glass is unavailable.

For multiple destinations, keep one bar above an IndexedStack so the lens can travel between pages.


Custom Icons #

Use standard icons or any Flutter widget, including SVGs, images, and custom painters. LiquidTabItem.icon is the concise option for Material icons; LiquidTabItem.custom accepts a widget and an optional activeIcon.

LiquidTabBar with custom icons and a purple theme
LiquidTabItem.custom(
  label: 'Explore',
  icon: SvgPicture.asset('assets/icons/explore.svg'),
  activeIcon: SvgPicture.asset('assets/icons/explore_filled.svg'),
  iconSize: 22,
  useThemeColor: false, // preserve multicolor artwork
)

Custom widgets are tinted with the theme's selected and unselected colors by default. Set useThemeColor: false to keep their original colors. The package accepts ordinary widgets and does not bundle an SVG or image library.

Keyboard behavior #

The bar moves above the keyboard by default. To keep it at the bottom for ordinary text fields, set liftAboveKeyboard: false and resizeToAvoidBottomInset: false on the host Scaffold. Built-in search still moves above the keyboard.


Styling & Optics #

LiquidTabBarTheme controls the selected and unselected colors, outer bar, selected lens, and refraction. It follows the app's light or dark brightness by default. Use LiquidTabBarTheme.adaptive(context) to also use the app's primary color, or pin a palette with LiquidTabBarTheme.dark().

theme: LiquidTabBarTheme.adaptive(context).copyWith(
  activeColor: const Color(0xFF007AFF),
  barStyle: LiquidBarStyle.glossy(),
  dropletRefraction: const DropletRefractionStyle.medium(),
),

Material tiers #

Tier Rendering
auto (default) Uses shader glass when supported; otherwise falls back to blur.
glass Fragment shaders sample and refract the backdrop (Impeller required).
blur Cross-platform frosted glass.
opaque Solid, high-contrast surface.

Glossy and light/dark styles #

LiquidBarStyle.glossy() follows ambient brightness. Pass brightness: to pin it. Glossy adds a clearer bevel while retaining the same glass family.

Glossy Light Glossy Dark
Glossy light bar Glossy dark bar
theme: LiquidTabBarTheme(barStyle: LiquidBarStyle.glossy()),

Outer bar appearance is set by LiquidBarStyle and GlassStyle. Presets include frosted, prismaticCaustics, clearCrystal, and deepRefraction. The selected lens surface is configured independently through LiquidDropletSurfaceStyle, including its gradient, border, and LiquidDropletShadow.

Droplet refraction #

The moving lens bends the icons and labels behind it; displacement and color separation fade at rest. DropletRefractionStyle presets are none(), subtle(), medium() (default), and strong(). Set dispersion: 0 to disable RGB separation while retaining refraction.

theme: const LiquidTabBarTheme(
  dropletRefraction: DropletRefractionStyle.strong(),
),

Advanced controls are thickness (bevel width), refractiveIndex, baseHeight (optical depth), dispersion, specularStrength, and refractionStrength. When omitted, the theme selects calibrated Normal or Glossy values. Explicit values are respected.

Actions & Placement #

Together Split
Action button next to the tab bar on iOS Action button at the opposite edge of the tab bar on iOS

Attach a standalone circular button (such as Create, Filter, or Search) alongside the navigation capsule:

separateAction: LiquidTabAction.icon(
  icon: Icons.add_rounded,
  tooltip: 'Create',
  onTap: handleCreate,
),
separateActionPlacement: LiquidTabActionPlacement.together, // or .split
  • LiquidTabActionPlacement.together (default): Groups the action circle adjacent to the main capsule.
  • LiquidTabActionPlacement.split: Pins the main capsule to the leading margin and the action button to the trailing margin.
  • Action styling: Customize the selected action background marker via actionStyle: const LiquidTabActionStyle(selectedFill: ...).

Notification Badges #

LiquidTabItem includes integrated notification badges with four display modes:

// 1. Unread dot
LiquidTabItem.icon(
  icon: Icons.mail_rounded,
  label: 'Inbox',
  badge: true,
),

// 2. Count pill (auto-formats 99+ above 99)
LiquidTabItem.icon(
  icon: Icons.notifications_rounded,
  label: 'Alerts',
  badge: true,
  badgeCount: 4,
),
  • Text pill: Pass badgeText: 'PRO' for custom string badges.
  • Custom widget: Supply badgeWidget for custom indicator layouts.
  • Styling: Configure colors, borders, typography, and offsets via LiquidBadgeStyle.
  • Optical interaction: Normal tab badges participate in droplet refraction when overlapped by the moving lens.

Expanded LiquidTabBar search field

Add an edge-to-edge search field with a separate search action:

separateAction: LiquidTabAction.search(
  hintText: 'Search notes…',
  clearOnClose: true,
  onChanged: filterResults,
  onSubmitted: submitSearch,
  customIcon: SvgPicture.asset('assets/icons/search.svg'), // optional
),

Search moves above the keyboard. Use the controller attached to the bar to call controller.openSearch() or controller.closeSearch(). Android back closes an active search before leaving the page. customIcon is also used in the expanded field; custom icons support useThemeColor like tab icons.

Adaptive Folding #

LiquidTabBar folded to the selected tab on iOS

When using LiquidTabBarScaffold, vertical scrolling in primary body scrollables automatically folds the bar into a compact pill showing only the active tab:

LiquidTabBarScaffold(
  body: ListView.builder(
    itemCount: 50,
    itemBuilder: (context, i) => ListTile(title: Text('Item $i')),
  ),
  tabBar: LiquidTabBar(
    shrinkOnScroll: true,                  // Set false to keep permanently expanded
    foldedShape: LiquidFoldedShape.circle, // .circle or .oval
    // ...
  ),
)

LiquidTabBarScaffold automatically observes primary vertical body scrolling; no NotificationListener or controller management is required for normal layouts. Scrolling back up, reaching the top of content, or tapping the folded capsule smoothly unfolds the bar.

Manual integration #

For custom Scaffold layouts, multiple independent vertical scroll sources, or complex nested scrolling, forward notifications explicitly:

final controller = LiquidTabBarController();

NotificationListener<ScrollNotification>(
  onNotification: controller.handleScroll,
  child: myScrollView,
)

LiquidTabBar(
  controller: controller,
  shrinkOnScroll: true,
  // ...
)

Controller, layout & accessibility #

LiquidTabBarScaffold is the recommended layout: it enables extendBody, reserves scroll space, and observes primary vertical scrolling for folding. With a regular Scaffold, set extendBody: true and add LiquidTabBar.reservedPadding(context) to scrollable content. For slivers, use SliverLiquidScrollPadding().

For manual scroll handling, forward notifications to LiquidTabBarController.handleScroll. The controller also exposes minimize(), expand(), openSearch(), closeSearch(), and performance governor status. Selection remains app-owned via selectedIndex and onSelected.

The bar follows ambient RTL directionality and provides screen-reader semantics. It respects MediaQuery.disableAnimationsOf(context) for reduced motion. LiquidFoldedShape.circle is the default; use .oval for an oval folded bar.


Advanced Governor Tuning #

When armed at startup via LiquidTabBarController.shared.armGovernor(), the governor monitors GPU raster timings during glass shader execution and automatically downgrades to backdrop blur if slow frames exceed default thresholds (rasterThresholdMs: 24, maxSlowFrames: 12).

For custom performance budgets, configure explicit thresholds on your controller:

final controller = LiquidTabBarController(
  governorConfig: const LiquidGovernorConfig(
    rasterThresholdMs: 20,
    maxSlowFrames: 8,
  ),
);
controller.armGovernor();

Example Application #

The repository includes interactive demonstrations:

  • 4-Style Comparison: Normal and Glossy bars in light and dark themes.
  • Basic Navigation: Standard bottom bar with fluid spring droplet.
  • Styling & Refraction: Custom materials, light/dark themes, and refraction presets.
  • Action Buttons: Together and Split action placements.
  • Search & Folding: Expandable search morphing, circle/oval folding, and live RTL layout.
  • Custom Icons Demo: Standard IconData, custom SVG widgets, activeIcon switching, theme tinting vs original multi-color artwork, custom Search glyphs, and Search glyph sizing.
  • Text Form Field: Keyboard behavior with the bar visible.
cd example
flutter run

2.0.0 migration #

Version 2.0.0 consolidates the public API around the droplet navigation bar and removes obsolete or duplicate options. See the migration guide for source changes.


Credits #

Version 2.0.0 consolidates the package around the droplet navigation bar. The bar, scaffold, refraction shader, search, actions, badges, style objects, and Android Impeller backdrop fix were created by Mohammed Hafiz (#5). Yousef Sobhy (#4) contributed the fold-and-unfold lens fixes in 1.0.1. The package originated in the Orderbase courier app.


License #

This package is licensed under the MIT License. See LICENSE for details.

2
likes
160
points
505
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

An iOS 26-style floating liquid-glass tab bar for Flutter with a deformable droplet, refraction, search, actions, badges, and scroll-aware folding.

Repository (GitHub)
View/report issues

Topics

#navigation #tabs #glassmorphism #ios #ui

License

MIT (license)

Dependencies

flutter

More

Packages that depend on liquid_tab_bar