curved_sidebar_navigation 0.1.0 copy "curved_sidebar_navigation: ^0.1.0" to clipboard
curved_sidebar_navigation: ^0.1.0 copied to clipboard

A configurable Flutter sidebar with an animated curved cutout for the selected navigation item.

example/lib/main.dart

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

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

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

  @override
  State<ExampleApp> createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  static const _violet = Color(0xFF5C54B7);
  static const _drawerWidth = 252.0;
  static const _items = [
    CurvedSidebarItem(value: 0, label: 'Profile', icon: Icons.person_outline),
    CurvedSidebarItem(value: 1, label: 'Projects', icon: Icons.work_outline),
    CurvedSidebarItem(
      value: 2,
      label: 'Settings',
      icon: Icons.settings_outlined,
    ),
  ];

  int selected = 0;

  CurvedSidebarNavigation<int> _navigation({
    required bool closeOnSelected,
    bool fillDrawer = false,
  }) {
    return CurvedSidebarNavigation<int>(
      selectedValue: selected,
      closeOnSelected: closeOnSelected,
      onSelected: (value) => setState(() => selected = value),
      backgroundColor: _violet,
      panelWidth: _drawerWidth,
      totalWidth: fillDrawer ? _drawerWidth : 306,
      header: const _ExampleBrand(),
      footer: const _ExampleFooter(),
      items: _items,
    );
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: _violet,
        scaffoldBackgroundColor: const Color(0xFFF1F5FC),
        useMaterial3: true,
      ),
      home: LayoutBuilder(
        builder: (context, constraints) {
          final desktop = constraints.maxWidth >= 800;
          if (desktop) {
            return Scaffold(
              body: Row(
                children: [
                  _navigation(closeOnSelected: false),
                  Expanded(child: _SelectedContent(selected: selected)),
                ],
              ),
            );
          }

          return Scaffold(
            drawerScrimColor: Colors.transparent,
            appBar: AppBar(title: const Text('Curved sidebar example')),
            drawer: Drawer(
              width: _drawerWidth,
              elevation: 0,
              shadowColor: Colors.transparent,
              surfaceTintColor: Colors.transparent,
              backgroundColor: const Color(0xFFF1F5FC),
              shape: const RoundedRectangleBorder(),
              child: SafeArea(
                child: _navigation(closeOnSelected: true, fillDrawer: true),
              ),
            ),
            body: _SelectedContent(selected: selected),
          );
        },
      ),
    );
  }
}

class _SelectedContent extends StatelessWidget {
  const _SelectedContent({required this.selected});

  final int selected;

  @override
  Widget build(BuildContext context) {
    const labels = ['Profile', 'Projects', 'Settings'];
    return Center(
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Icon(Icons.touch_app_outlined, size: 44),
          const SizedBox(height: 14),
          Text(
            labels[selected],
            style: Theme.of(context).textTheme.headlineMedium,
          ),
          const SizedBox(height: 8),
          Text(
            MediaQuery.sizeOf(context).width >= 800
                ? 'Permanent sidebar mode'
                : 'Open the drawer and select another destination',
          ),
        ],
      ),
    );
  }
}

class _ExampleBrand extends StatelessWidget {
  const _ExampleBrand();

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        'MY APP',
        style: TextStyle(
          color: Colors.white,
          fontWeight: FontWeight.w800,
          letterSpacing: 1.2,
        ),
      ),
    );
  }
}

class _ExampleFooter extends StatelessWidget {
  const _ExampleFooter();

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 210,
      padding: const EdgeInsets.all(14),
      decoration: BoxDecoration(
        color: Colors.white.withValues(alpha: .12),
        borderRadius: BorderRadius.circular(18),
      ),
      child: const Text(
        'Responsive sidebar\nand drawer',
        textAlign: TextAlign.center,
        style: TextStyle(color: Colors.white),
      ),
    );
  }
}
2
likes
160
points
124
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A configurable Flutter sidebar with an animated curved cutout for the selected navigation item.

Homepage
Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

flutter

More

Packages that depend on curved_sidebar_navigation