pub version License: MIT Flutter GitHub Sponsors GitHub forks GitHub issues GitHub issues

A highly customizable curved bottom navigation bar featuring a smooth animated notch, gliding elastic FAB bubble, Notification Badges, Labels, 10 presets, and Lottie/SVG/Image/Widget icon support.

Tuning

Everyone loves tuning. For some it will be girls, for some carburators and for some it will be navigation bar ๐Ÿฅฒ. If you are among them, you are in the right place. Let's tune the navigation bar. You can change almost every parameter of the navigation bar.

Features

  • Animated notch that slides smoothly to the selected item
  • Elastic pop-in animation for the FAB bubble
  • Mathematically continuous Cยน shoulder curves (no kinks at the notch edges)
  • Notification badges
  • 10 built-in style presets
  • Lottie, SVG, Image or any Widget support for Icons
  • Zero dependencies beyond Flutter

Preview

Installation

Add to your pubspec.yaml:

dependencies:
  curved_navigation_bar_pro: ^2.0.6

Then run:

flutter pub get

Quick start

import 'package:curved_navigation_bar_pro/curved_navigation_bar_pro.dart';

class MyPage extends StatefulWidget {
  const MyPage({super.key});
  @override
  State<MyPage> createState() => _MyPageState();
}

class _MyPageState extends State<MyPage> {
  int _index = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ...,
      bottomNavigationBar: CurvedNavigationBarPro(
        items: const [
          CurvedNavigationItemPro(
            inactiveIcon: Icons.home_outlined,
            activeIcon: Icons.home_rounded,
            label: 'Home',
          ),
          CurvedNavigationItemPro(
            inactiveIcon: Icons.favorite_outline,
            activeIcon: Icons.favorite_rounded,
            label: 'Saved',
          ),
          CurvedNavigationItemPro(
            inactiveIcon: Icons.person_outline_rounded,
            activeIcon: Icons.person_rounded,
            label: 'Profile',
          ),
        ],
        currentIndex: _index,
        onTap: (i) => setState(() => _index = i),
      ),
    );
  }
}

Customisation

CurvedNavigationBarPro(
  items: ...,
  currentIndex: _index,
  onTap: (i) => setState(() => _index = i),

  // Colours
  backgroundColor: Colors.white,
  activeColor: Colors.indigo,
  activeIconColor: Colors.white,
  inactiveColor: const Color(0xFFADB5BD),
  fabColor: Colors.indigo,

  // Geometry
  barHeight: 110,
  fabRadius: 28,
  fabGap: 10,
  fabSink: 22,
  notchShoulderRadius: 12,
  cornerRadius: 16,
  contentPadding: 8,

  // Shadow
  elevation: 14,
  shadowColor: Colors.black26,

  // Animation
  animationDuration: const Duration(milliseconds: 400),
  animationCurve: Curves.easeInOutCubic,

  // Text styles (optional overrides)
  activeTextStyle: const TextStyle(fontSize: 11, fontWeight: FontWeight.w800),
  inactiveTextStyle: const TextStyle(fontSize: 10, fontWeight: FontWeight.w400),

  // Icon sizes
  inactiveIconSize: 24,
  activeIconSize: 22,
)

Badges

Add notification badges to any navigation item to display counts, dots, or custom widgets:

CurvedNavigationBarPro(
  items: [
    CurvedNavigationItemPro(
      inactiveIcon: Icons.home_outlined,
      activeIcon: Icons.home_rounded,
      label: 'Home',
      badgeText: '3',  // Shows a red badge with "3"
    ),
    CurvedNavigationItemPro(
      inactiveIcon: Icons.mail_outline,
      activeIcon: Icons.mail_rounded,
      label: 'Messages',
      badgeText: 'โ€ข',  // Shows a dot badge
    ),
    CurvedNavigationItemPro(
      inactiveIcon: Icons.notifications_outlined,
      activeIcon: Icons.notifications_rounded,
      label: 'Alerts',
      badgeText: '99+',
      badgeColor: Colors.orange,  // Custom badge colour
      badgeTextColor: Colors.black,  // Custom text colour
    ),
    CurvedNavigationItemPro(
      inactiveIcon: Icons.shopping_cart_outlined,
      activeIcon: Icons.shopping_cart_rounded,
      label: 'Cart',
      badgeWidget: Container(  // Fully custom badge widget
        width: 20,
        height: 20,
        decoration: const BoxDecoration(
          color: Colors.red,
          shape: BoxShape.circle,
        ),
        child: const Center(
          child: Text('5', style: TextStyle(color: Colors.white, fontSize: 10)),
        ),
      ),
    ),
  ],
  currentIndex: _index,
  onTap: (i) => setState(() => _index = i),
)

Badge properties

Property Type Default Description
badgeText String? null Text to display in the badge (e.g. "3", "99+", "โ€ข")
badgeColor Color? Color(0xFFE53935) Background colour of the badge
badgeTextColor Color? Colors.white Text colour inside the badge
badgeWidget Widget? null Custom widget to display as the badge (overrides text-based badge)

Built-in Style Presets

Choose from 10 ready-made styles with a single navbarStyle parameter. Every individual parameter you pass overrides the preset value โ€” so presets are a starting point, not a constraint.

Apply a preset

CurvedNavigationBarPro(
  items: myItems,
  onTap: (i) => setState(() => _index = i),
  currentIndex: _index,
  navbarStyle: CNBPStyles.goldenHour, // full Golden Hour theme in one line
)

Apply a preset and override one value

CurvedNavigationBarPro(
  items: myItems,
  onTap: (i) => setState(() => _index = i),
  currentIndex: _index,
  navbarStyle: CNBPStyles.berryBlossom,
  fabRadius: 32,       // โ† overrides only this; everything else stays preset
)

Use preset data directly

// Read a preset's values for your own logic
final data = CNBPStyles.royalAmethyst.data;
print(data.activeColor); // Color(0xFFBE73FF)

// Or tweak a preset into a custom CNBPStyleData object
final myStyle = CNBPStyles.arcticFrost.data.copyWith(
  cornerRadius: 0,
  elevation: 16,
);

Available presets

CNBPStyles.* Bar background Accent colour Highlights
classicIndigo White #6C63FF indigo Default look, standard geometry
deepSpaceDark #1A1A2E charcoal #00E5FF cyan Sharp notch, spaced-caps labels
roundedCoral White #FF6B6B coral Pill corners (cornerRadius: 28), smooth shoulders
minimalMono White #2D3748 slate Fully sunk FAB, sharp notch, monochrome
emeraldPill #0F2D26 dark green #00C896 emerald Large FAB, rounded corners, suits 5 items
sunsetAmber White #FF9F43 amber Travel theme, smooth shoulders, easeInOutSine
royalAmethyst #0E0829 deep navy #BE73FF lavender Large protruding FAB, suits 3 items, easeOutBack
arcticFrost #F0F4F8 steel grey #2B6CB0 steel blue Fully sunk FAB, pill corners, light theme
berryBlossom #1C0A1C dark purple #FF6AC1 hot pink Ultra-smooth notch, suits 5 items, elasticOut
goldenHour #121008 ink black #FFD700 gold Dark icon in FAB, finance theme, easeInOutCubic

Example with Lottie and Svg

CurvedNavigationBarPro(
  items: [
    // Lottie Example
    CurvedNavigationItemPro(
      activeWidget: Lottie.asset(
        'lotties/cart.json',
        repeat: false,
        width: 25,
      ),
      inactiveWidget: Lottie.asset(
        'lotties/cart.json',
        repeat: false,
        animate: false,
        width: 25,
      ),
      label: 'Cart',
    ),

    // Svg Example
    CurvedNavigationItemPro(
      activeWidget: SvgPicture.asset(
        'assets/images/profile_fill.svg',
        colorFilter: const ColorFilter.mode(
          Colors.white,
          BlendMode.srcIn,
        ),
        width: 25,
      ),
      inactiveWidget: SvgPicture.asset(
        'assets/images/profile.svg',
        colorFilter: const ColorFilter.mode(
          Colors.green,
          BlendMode.srcIn,
        ),
        width: 25,
      ),
      label: 'Profile',
    ),
  ],
  currentIndex: _index,
  onTap: (i) => setState(() => _index = i),
)

Note: Keep in mind to set the repeat as false for Lottie and set the colorFilter for Svg for a better user experience.

API Reference

CurvedNavigationBarPro

Property Type Default Description
items List<CurvedNavigationItemPro> required 2โ€“6 navigation items
onTap ValueChanged<int> required Callback when an item is tapped
currentIndex int 0 Selected item index
navbarStyle CNBPStyles? null Built-in preset โ€” supplies defaults for all visual params
backgroundColor Color? preset โ†’ Colors.white Bar background
activeColor Color? preset โ†’ theme primary Active label & default FAB colour
activeIconColor Color? preset โ†’ Colors.white Icon colour inside the FAB bubble
inactiveColor Color? preset โ†’ #ADB5BD Inactive icon & label colour
fabColor Color? preset โ†’ activeColor FAB bubble background
barHeight double? preset โ†’ 110 Bar height in logical pixels
fabRadius double? preset โ†’ 24 FAB bubble radius
fabGap double? preset โ†’ 10 Gap between FAB edge and notch arc
fabSink double? preset โ†’ 22 Pixels the FAB centre sinks below the bar top
notchShoulderRadius double? preset โ†’ 12 Shoulder fillet radius (0 = sharp corners)
cornerRadius double? preset โ†’ 0 Top-left / top-right bar corner radius
contentPadding double? preset โ†’ cornerRadius Horizontal padding on both ends of the items row
elevation double? preset โ†’ 14 Shadow depth
shadowColor Color? preset โ†’ rgba(0,0,0,0.16) Shadow colour
animationDuration Duration? preset โ†’ 400 ms Notch slide duration
animationCurve Curve? preset โ†’ easeInOutCubic Notch slide curve
activeTextStyle TextStyle? preset โ†’ built-in Override active label style
inactiveTextStyle TextStyle? preset โ†’ built-in Override inactive label style
showLabel bool? preset โ†’ true Toggle visibility of labels below the icons
inactiveIconSize double? preset โ†’ 24.0 Icon size for inactive nav items
activeIconSize double? preset โ†’ fabRadius ร— 0.92 Icon size inside the FAB bubble

Resolution order: explicit parameter โ†’ navbarStyle preset โ†’ hardcoded default

CurvedNavigationItemPro

Property Type Description
inactiveIcon IconData? Icon shown when inactive (ignored if inactiveWidget is provided)
activeIcon IconData? Icon shown when active (ignored if activeWidget is provided)
inactiveWidget Widget? Custom widget shown when inactive (takes priority over inactiveIcon)
activeWidget Widget? Custom widget shown when active (takes priority over activeIcon)
label String Label text beneath the icon
badgeText String? Optional notification badge text (e.g. "3", "99+", "โ€ข")
badgeColor Color? Optional badge background colour (defaults to #E53935)
badgeTextColor Color? Optional badge text colour (defaults to Colors.white)
badgeWidget Widget? Optional custom widget to display as the badge (overrides text-based badge)

Note: You must provide at least one of inactiveIcon or inactiveWidget.

Running the example

cd example
flutter run

Contributing

PRs and issues are welcome! Please open an issue first for significant changes.

License

Made with ๐Ÿ’› by aslamambiloly ยฉ 2026

Libraries

curved_navigation_bar_pro
A beautiful Flutter curved bottom navigation bar with an animated curved notch FAB, smooth elastic bubble animation, and fully customisable theming.