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

vasX UI — a collection of beautiful, reusable Flutter widgets including smart dropdowns, date pickers, multi-step wizards, animated popup menus, and responsive data tables. Built for production-grade [...]

example/lib/main.dart

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

void main() {
  runApp(const VasxUiExampleApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'vasX UI Examples',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorSchemeSeed: VasxColors.primary,
        useMaterial3: true,
      ),
      home: const ExampleHomePage(),
    );
  }
}

// ─────────────────────────────────────────────
// Home Page — widget gallery navigation
// ─────────────────────────────────────────────
class ExampleHomePage extends StatelessWidget {
  const ExampleHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    final sections = [
      _GalleryItem('AppPopupMenu', Icons.more_vert,
          const AppPopupMenuExample()),
      _GalleryItem(
          'CustomTable', Icons.table_chart_outlined, const CustomTableExample()),
      _GalleryItem('VerticalWizardShell', Icons.linear_scale,
          const VerticalWizardExample()),
      _GalleryItem('ScrollableWizardShell', Icons.view_stream_outlined,
          const ScrollableWizardExample()),
      _GalleryItem('SearchableDropdown', Icons.search,
          const SearchableDropdownExample()),
      _GalleryItem('MultiSelectDropdown', Icons.checklist,
          const MultiSelectDropdownExample()),
      _GalleryItem(
          'CreatableDropdown', Icons.add_box_outlined, const CreatableDropdownExample()),
      _GalleryItem('DropdownDatePicker', Icons.calendar_month_outlined,
          const DropdownDatePickerExample()),
      _GalleryItem('DateRangePicker', Icons.date_range,
          const DateRangePickerExample()),
      _GalleryItem('CrmCalendar', Icons.calendar_month,
          const CrmCalendarExample()),
      _GalleryItem('CrmStatsDashboard', Icons.dashboard_outlined,
          const CrmStatsDashboardExample()),
      _GalleryItem('Form', Icons.dynamic_form_outlined,
          const CustomFormExample()),
      _GalleryItem('Buttons & Action Bar', Icons.smart_button_outlined,
          const ButtonsExample()),
      _GalleryItem('Toggle Switch', Icons.toggle_on_outlined,
          const ToggleExample()),
      _GalleryItem('Checkbox', Icons.check_box_outlined,
          const CheckboxExample()),
      _GalleryItem('AI Assistant SearchBar', Icons.auto_awesome_outlined,
          const AiSearchBarExample()),
      _GalleryItem('Payment Confirmation Popup', Icons.receipt_long_outlined,
          const PaymentConfirmationExample()),
      _GalleryItem('Alert Banners', Icons.notifications_active_outlined,
          const AlertExample()),
      _GalleryItem('Side Menu (E-Commerce)', Icons.menu_open_rounded,
          const SideMenuExample()),
      _GalleryItem('Mobile Bottom NavBar', Icons.navigation_rounded,
          const BottomNavBarExample()),
    ];

    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(
        title: const Text('vasX UI Widget Gallery'),
        backgroundColor: VasxColors.primary,
        foregroundColor: Colors.white,
      ),
      body: ListView.builder(
        padding: const EdgeInsets.all(20),
        itemCount: sections.length,
        itemBuilder: (context, index) {
          final item = sections[index];
          return Card(
            margin: const EdgeInsets.only(bottom: 12),
            shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(12)),
            child: ListTile(
              leading: Icon(item.icon, color: VasxColors.primary),
              title: Text(item.title,
                  style: const TextStyle(
                      fontWeight: FontWeight.w600,
                      color: VasxColors.textPrimary)),
              trailing:
                  const Icon(Icons.arrow_forward_ios, size: 16),
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (_) => item.page),
              ),
            ),
          );
        },
      ),
    );
  }
}

class _GalleryItem {
  final String title;
  final IconData icon;
  final Widget page;
  const _GalleryItem(this.title, this.icon, this.page);
}

// ─────────────────────────────────────────────
// AppPopupMenu Example
// ─────────────────────────────────────────────
class AppPopupMenuExample extends StatefulWidget {
  const AppPopupMenuExample({super.key});

  @override
  State<AppPopupMenuExample> createState() => _AppPopupMenuExampleState();
}

class _AppPopupMenuExampleState extends State<AppPopupMenuExample> {
  String _lastAction = 'No action yet';

  void _showMenu(BuildContext context) {
    final overlay = Overlay.of(context);
    late OverlayEntry entry;
    entry = OverlayEntry(
      builder: (_) => Positioned(
        top: 120,
        right: 24,
        child: AppPopupMenu(
          onClose: () => entry.remove(),
          items: [
            AppPopupMenuItem(
              label: 'Edit',
              icon: Icons.edit_outlined,
              onTap: () {
                if (mounted) setState(() => _lastAction = 'Edit tapped');
              },
            ),
            AppPopupMenuItem(
              label: 'Duplicate',
              icon: Icons.copy_outlined,
              onTap: () {
                if (mounted) setState(() => _lastAction = 'Duplicate tapped');
              },
            ),
            AppPopupMenuItem(
              label: 'Delete',
              icon: Icons.delete_outline,
              isDestructive: true,
              onTap: () {
                if (mounted) setState(() => _lastAction = 'Delete tapped');
              },
            ),
          ],
        ),
      ),
    );
    overlay.insert(entry);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('AppPopupMenu')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton.icon(
              onPressed: () => _showMenu(context),
              icon: const Icon(Icons.more_vert),
              label: const Text('Show Popup Menu'),
            ),
            const SizedBox(height: 24),
            Text('Last: $_lastAction',
                style: const TextStyle(fontSize: 16)),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// CustomTable Example
// ─────────────────────────────────────────────
class CustomTableExample extends StatelessWidget {
  const CustomTableExample({super.key});

  @override
  Widget build(BuildContext context) {
    final data = [
      ['Alice Johnson', 'Class 10-A', 'alice@school.com'],
      ['Bob Smith', 'Class 9-B', 'bob@school.com'],
      ['Carol White', 'Class 11-C', 'carol@school.com'],
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('CustomTable')),
      body: Padding(
        padding: const EdgeInsets.all(20),
        child: CustomTable(
          columns: const [
            CustomTableColumn(label: 'Name', flex: 2),
            CustomTableColumn(label: 'Class'),
            CustomTableColumn(label: 'Email', flex: 2),
          ],
          itemCount: data.length,
          minWidth: 600,
          rowBuilder: (context, index) => [
            Text(data[index][0]),
            Text(data[index][1]),
            Text(data[index][2]),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// VerticalWizardShell Example
// ─────────────────────────────────────────────
class VerticalWizardExample extends StatefulWidget {
  const VerticalWizardExample({super.key});

  @override
  State<VerticalWizardExample> createState() =>
      _VerticalWizardExampleState();
}

class _VerticalWizardExampleState extends State<VerticalWizardExample> {
  int _step = 0;

  static const _steps = [
    WizardStepConfig(
      icon: Icons.person_outline_rounded,
      label: 'Personal Info',
      mobileLabel: 'Personal',
      subtitle: 'Name & contact',
    ),
    WizardStepConfig(
      icon: Icons.location_on_outlined,
      label: 'Address',
      mobileLabel: 'Address',
      subtitle: 'Current address',
    ),
    WizardStepConfig(
      icon: Icons.check_circle_outline,
      label: 'Review',
      mobileLabel: 'Review',
      subtitle: 'Confirm details',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return VerticalWizardShell(
      steps: _steps,
      currentStep: _step,
      title: 'Registration Wizard',
      formContent: Padding(
        padding: const EdgeInsets.all(8),
        child: Text(
          'Step ${_step + 1} form content goes here.',
          style: const TextStyle(fontSize: 16),
        ),
      ),
      onBack: _step > 0
          ? () => setState(() => _step--)
          : null,
      onNext: _step < _steps.length - 1
          ? () => setState(() => _step++)
          : () {
              ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Wizard complete!')),
              );
              Navigator.pop(context);
            },
      nextLabel: _step == _steps.length - 1 ? 'Finish' : 'Next',
      onCancel: () => Navigator.pop(context),
    );
  }
}

// ─────────────────────────────────────────────
// ScrollableWizardShell Example
// ─────────────────────────────────────────────
class ScrollableWizardExample extends StatefulWidget {
  const ScrollableWizardExample({super.key});

  @override
  State<ScrollableWizardExample> createState() =>
      _ScrollableWizardExampleState();
}

class _ScrollableWizardExampleState
    extends State<ScrollableWizardExample> {
  bool _saving = false;

  static const _steps = [
    WizardStepConfig(
      icon: Icons.person_outline_rounded,
      label: 'Core Details',
      mobileLabel: 'Core',
      subtitle: 'Name & roll number',
    ),
    WizardStepConfig(
      icon: Icons.description_outlined,
      label: 'Basic Details',
      mobileLabel: 'Basic',
      subtitle: 'Class & contact info',
    ),
    WizardStepConfig(
      icon: Icons.location_on_outlined,
      label: 'Address',
      mobileLabel: 'Address',
      subtitle: 'Current address',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return ScrollableWizardShell(
      steps: _steps,
      title: 'Create Student',
      sectionContents: List.generate(
        _steps.length,
        (i) => Padding(
          padding: const EdgeInsets.all(8),
          child: Text(
            'Section ${i + 1} — ${_steps[i].label}.\nAdd your form fields here.',
            style: const TextStyle(fontSize: 15),
          ),
        ),
      ),
      saving: _saving,
      onSave: () async {
        setState(() => _saving = true);
        await Future.delayed(const Duration(seconds: 2));
        if (!context.mounted) return;
        setState(() => _saving = false);
        ScaffoldMessenger.of(context).showSnackBar(
          const SnackBar(content: Text('Saved!')),
        );
      },
      onCancel: () => Navigator.pop(context),
    );
  }
}

// ─────────────────────────────────────────────
// SearchableDropdown Example
// ─────────────────────────────────────────────
class SearchableDropdownExample extends StatefulWidget {
  const SearchableDropdownExample({super.key});

  @override
  State<SearchableDropdownExample> createState() =>
      _SearchableDropdownExampleState();
}

class _SearchableDropdownExampleState
    extends State<SearchableDropdownExample> {
  String? _selected;

  static const _countries = [
    'India', 'United States', 'United Kingdom', 'Canada',
    'Australia', 'Germany', 'France', 'Japan', 'Brazil', 'South Africa',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('SearchableDropdown')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            SearchableDropdown(
              label: 'Country',
              value: _selected,
              hint: 'Select a country',
              items: _countries,
              onChanged: (val) => setState(() => _selected = val),
            ),
            const SizedBox(height: 24),
            if (_selected != null)
              Text('Selected: $_selected',
                  style: const TextStyle(
                      fontSize: 16, color: VasxColors.primary)),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// MultiSelectSearchableDropdown Example
// ─────────────────────────────────────────────
class MultiSelectDropdownExample extends StatefulWidget {
  const MultiSelectDropdownExample({super.key});

  @override
  State<MultiSelectDropdownExample> createState() =>
      _MultiSelectDropdownExampleState();
}

class _MultiSelectDropdownExampleState
    extends State<MultiSelectDropdownExample> {
  List<String> _selected = [];

  static const _subjects = [
    'Mathematics', 'Physics', 'Chemistry', 'Biology',
    'English', 'History', 'Geography', 'Computer Science',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('MultiSelectSearchableDropdown')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            MultiSelectSearchableDropdown(
              label: 'Subjects',
              values: _selected,
              hint: 'Pick subjects',
              items: _subjects,
              onChanged: (vals) => setState(() => _selected = vals),
            ),
            const SizedBox(height: 24),
            if (_selected.isNotEmpty)
              Text('Selected: ${_selected.join(', ')}',
                  style: const TextStyle(fontSize: 14)),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// CreatableDropdown Example
// ─────────────────────────────────────────────
class CreatableDropdownExample extends StatefulWidget {
  const CreatableDropdownExample({super.key});

  @override
  State<CreatableDropdownExample> createState() =>
      _CreatableDropdownExampleState();
}

class _CreatableDropdownExampleState
    extends State<CreatableDropdownExample> {
  final List<String> _classes = ['Class 10-A', 'Class 10-B', 'Class 11-A'];
  String _selected = 'Class 10-A';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CreatableDropdown')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text('Class', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w500)),
            const SizedBox(height: 8),
            CreatableDropdown(
              value: _selected,
              items: _classes,
              onChanged: (val) => setState(() => _selected = val),
              onAddItem: (newClass) =>
                  setState(() {
                    _classes.add(newClass);
                    _selected = newClass;
                  }),
              onRemoveItem: (cls) => setState(() {
                _classes.remove(cls);
                if (_selected == cls) _selected = _classes.first;
              }),
            ),
            const SizedBox(height: 24),
            Text('Selected: $_selected',
                style: const TextStyle(fontSize: 14)),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// DropdownDatePicker Example
// ─────────────────────────────────────────────
class DropdownDatePickerExample extends StatefulWidget {
  const DropdownDatePickerExample({super.key});

  @override
  State<DropdownDatePickerExample> createState() =>
      _DropdownDatePickerExampleState();
}

class _DropdownDatePickerExampleState
    extends State<DropdownDatePickerExample> {
  final _dobController = TextEditingController();

  @override
  void dispose() {
    _dobController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('DropdownDatePicker')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            DropdownDatePicker(
              controller: _dobController,
              label: 'Date of Birth',
              startYear: 1950,
              endYear: 2010,
              showExtendYears: true,
            ),
            const SizedBox(height: 24),
            ValueListenableBuilder(
              valueListenable: _dobController,
              builder: (_, val, __) => Text(
                'Controller value: ${val.text.isEmpty ? "—" : val.text}',
                style: const TextStyle(fontSize: 14),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// DateRangePicker Example
// ─────────────────────────────────────────────
class DateRangePickerExample extends StatefulWidget {
  const DateRangePickerExample({super.key});

  @override
  State<DateRangePickerExample> createState() =>
      _DateRangePickerExampleState();
}

class _DateRangePickerExampleState
    extends State<DateRangePickerExample> {
  DateTimeRange? _range;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CustomDateRangePicker')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            ElevatedButton.icon(
              icon: const Icon(Icons.date_range),
              label: const Text('Pick Date Range'),
              onPressed: () async {
                final result = await showCustomDateRangePicker(
                  context: context,
                  initialDateRange: _range,
                );
                if (result != null) setState(() => _range = result);
              },
            ),
            const SizedBox(height: 24),
            if (_range != null)
              Text(
                'From: ${_range!.start.toLocal().toString().split(' ').first}\n'
                'To:   ${_range!.end.toLocal().toString().split(' ').first}',
                textAlign: TextAlign.center,
                style: const TextStyle(fontSize: 16),
              ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// CrmCalendar Example
// ─────────────────────────────────────────────
class CrmCalendarExample extends StatefulWidget {
  const CrmCalendarExample({super.key});

  @override
  State<CrmCalendarExample> createState() => _CrmCalendarExampleState();
}

class _CrmCalendarExampleState extends State<CrmCalendarExample> {
  final List<CrmCalendarEvent> _events = [
    CrmCalendarEvent(
      id: '1',
      name: 'Rahul Sharma',
      date: DateTime.now(),
      time: '10:30 AM',
      stage: 'Visit Scheduled',
      notes: 'Campus tour requested for Engineering program.',
    ),
    CrmCalendarEvent(
      id: '2',
      name: 'Priya Patel',
      date: DateTime.now(),
      time: '02:00 PM',
      stage: 'Interview Call',
      notes: 'MBA scholarship evaluation interview.',
    ),
    CrmCalendarEvent(
      id: '3',
      name: 'Aarav Kumar',
      date: DateTime.now().add(const Duration(days: 1)),
      time: '11:00 AM',
      stage: 'New Lead',
      notes: 'Enquired via website form.',
    ),
    CrmCalendarEvent(
      id: '4',
      name: 'Ananya Verma',
      date: DateTime.now().add(const Duration(days: 2)),
      time: '03:30 PM',
      stage: 'Admission Offered',
      notes: 'Offer letter dispatched.',
    ),
    CrmCalendarEvent(
      id: '5',
      name: 'Vikram Singh',
      date: DateTime.now().subtract(const Duration(days: 1)),
      time: '09:30 AM',
      stage: 'Follow-up Required',
      notes: 'Pending fee structure discussion.',
    ),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CrmCalendar')),
      body: CrmCalendar(
        events: _events,
        onEventView: (id) {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Viewing event ID: $id')),
          );
        },
        onEventEdit: (id) {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text('Editing event ID: $id')),
          );
        },
        onPickDate: () async {
          return await showDatePicker(
            context: context,
            initialDate: DateTime.now(),
            firstDate: DateTime(2020),
            lastDate: DateTime(2030),
          );
        },
      ),
    );
  }
}

// ─────────────────────────────────────────────
// CrmStatsDashboard Example
// ─────────────────────────────────────────────
class CrmStatsDashboardExample extends StatefulWidget {
  const CrmStatsDashboardExample({super.key});

  @override
  State<CrmStatsDashboardExample> createState() =>
      _CrmStatsDashboardExampleState();
}

class _CrmStatsDashboardExampleState extends State<CrmStatsDashboardExample> {
  final Map<String, int> _leadsByStage = {
    'New Lead': 45,
    'Contacted': 32,
    'Follow-up Required': 18,
    'Interested': 28,
    'Visit Scheduled': 14,
    'Application Started': 22,
    'Interview Call': 10,
    'Admission Offered': 16,
    'Waitlisted': 5,
    'Lost Lead': 8,
    'Re-engaged': 12,
    'Cold Lead': 9,
  };

  final List<CrmTrendData> _trendData = List.generate(
    15,
    (i) => CrmTrendData(
      date: '2026-08-${(i + 1).toString().padLeft(2, '0')}',
      value: (15 + (i * 7) % 35).toDouble(),
    ),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('CrmStatsDashboard')),
      body: CrmStatsDashboard(
        totalLeads: 219,
        archivedLeadsCount: 24,
        leadsByStage: _leadsByStage,
        trendData: _trendData,
        startDate: DateTime(2026, 8, 1),
        endDate: DateTime(2026, 8, 15),
        onDateRangeTap: () {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Date range filter tapped')),
          );
        },
        onViewArchived: () {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('Archived leads tapped')),
          );
        },
        onViewAllApplications: () {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('View all applications tapped')),
          );
        },
        onViewLogs: () {
          if (!mounted) return;
          ScaffoldMessenger.of(context).showSnackBar(
            const SnackBar(content: Text('View logs tapped')),
          );
        },
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Buttons & Action Bar Example
// ─────────────────────────────────────────────
class ButtonsExample extends StatefulWidget {
  const ButtonsExample({super.key});

  @override
  State<ButtonsExample> createState() => _ButtonsExampleState();
}

class _ButtonsExampleState extends State<ButtonsExample> {
  String _searchQuery = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxButton & VasxSearchBar')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Action Bar (Reference Design)',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 12),
            Container(
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: VasxColors.borderLight),
              ),
              child: SingleChildScrollView(
                scrollDirection: Axis.horizontal,
                child: Row(
                  children: [
                    VasxSearchBar(
                      hintText: 'Search...',
                      width: 240,
                      onChanged: (q) => setState(() => _searchQuery = q),
                    ),
                    const SizedBox(width: 12),
                    VasxButton(
                      label: 'Filter',
                      icon: Icons.filter_list_rounded,
                      variant: VasxButtonVariant.secondary,
                      onPressed: () {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(content: Text('Filter pressed')),
                        );
                      },
                    ),
                    const SizedBox(width: 12),
                    VasxButton(
                      label: 'Create Student',
                      icon: Icons.add_rounded,
                      variant: VasxButtonVariant.primary,
                      onPressed: () {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(content: Text('Create Student pressed')),
                        );
                      },
                    ),
                    const SizedBox(width: 12),
                    VasxButton(
                      label: 'Bulk PDF',
                      icon: Icons.picture_as_pdf_outlined,
                      variant: VasxButtonVariant.outlined,
                      onPressed: () {
                        ScaffoldMessenger.of(context).showSnackBar(
                          const SnackBar(content: Text('Bulk PDF pressed')),
                        );
                      },
                    ),
                  ],
                ),
              ),
            ),
            if (_searchQuery.isNotEmpty) ...[
              const SizedBox(height: 8),
              Text('Search query: $_searchQuery', style: TextStyle(color: Colors.grey[600])),
            ],
            const SizedBox(height: 32),
            const Text(
              'Button Variants & Sizes',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 12),
            Wrap(
              spacing: 12,
              runSpacing: 12,
              crossAxisAlignment: WrapCrossAlignment.center,
              children: [
                const VasxButton(label: 'Small', size: VasxButtonSize.small),
                const VasxButton(label: 'Medium', size: VasxButtonSize.medium),
                const VasxButton(label: 'Large', size: VasxButtonSize.large),
                const VasxButton(label: 'Loading', isLoading: true),
                VasxButton(
                  label: 'Disabled',
                  variant: VasxButtonVariant.outlined,
                  onPressed: null,
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Toggle Switch Example
// ─────────────────────────────────────────────
class ToggleExample extends StatefulWidget {
  const ToggleExample({super.key});

  @override
  State<ToggleExample> createState() => _ToggleExampleState();
}

class _ToggleExampleState extends State<ToggleExample> {
  bool _activeToggle = true;
  bool _inactiveToggle = false;
  bool _labeledToggle = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxToggle')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Toggle Switch States (Reference Design)',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(24),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(16),
                border: Border.all(color: VasxColors.borderLight),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      const Text('Active State: ', style: TextStyle(fontWeight: FontWeight.w500)),
                      const SizedBox(width: 12),
                      VasxToggle(
                        value: _activeToggle,
                        onChanged: (val) => setState(() => _activeToggle = val),
                      ),
                    ],
                  ),
                  const SizedBox(height: 24),
                  Row(
                    children: [
                      const Text('Inactive State: ', style: TextStyle(fontWeight: FontWeight.w500)),
                      const SizedBox(width: 12),
                      VasxToggle(
                        value: _inactiveToggle,
                        onChanged: (val) => setState(() => _inactiveToggle = val),
                      ),
                    ],
                  ),
                  const SizedBox(height: 24),
                  const Divider(),
                  const SizedBox(height: 16),
                  VasxToggle(
                    value: _labeledToggle,
                    label: 'Enable Automated Email Notifications',
                    onChanged: (val) => setState(() => _labeledToggle = val),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Checkbox Example
// ─────────────────────────────────────────────
class CheckboxExample extends StatefulWidget {
  const CheckboxExample({super.key});

  @override
  State<CheckboxExample> createState() => _CheckboxExampleState();
}

class _CheckboxExampleState extends State<CheckboxExample> {
  bool _checked1 = true;
  bool _checked2 = false;
  bool _termsChecked = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxCheckbox')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Checkbox States (Reference Design)',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            Container(
              padding: const EdgeInsets.all(24),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(16),
                border: Border.all(color: VasxColors.borderLight),
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Row(
                    children: [
                      const Text('Checked State: ', style: TextStyle(fontWeight: FontWeight.w500)),
                      const SizedBox(width: 12),
                      VasxCheckbox(
                        value: _checked1,
                        onChanged: (val) => setState(() => _checked1 = val),
                      ),
                    ],
                  ),
                  const SizedBox(height: 24),
                  Row(
                    children: [
                      const Text('Unchecked State: ', style: TextStyle(fontWeight: FontWeight.w500)),
                      const SizedBox(width: 12),
                      VasxCheckbox(
                        value: _checked2,
                        onChanged: (val) => setState(() => _checked2 = val),
                      ),
                    ],
                  ),
                  const SizedBox(height: 24),
                  const Divider(),
                  const SizedBox(height: 16),
                  VasxCheckbox(
                    value: _termsChecked,
                    label: 'I accept the Terms of Service and Privacy Policy',
                    onChanged: (val) => setState(() => _termsChecked = val),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// CustomForm Example
// ─────────────────────────────────────────────
class CustomFormExample extends StatefulWidget {
  const CustomFormExample({super.key});

  @override
  State<CustomFormExample> createState() => _CustomFormExampleState();
}

class _CustomFormExampleState extends State<CustomFormExample> {
  final _hostController = TextEditingController(text: 'smtp.gmail.com');
  final _portController = TextEditingController(text: '587');
  final _usernameController =
      TextEditingController(text: 'admin@vasxui.com');
  final _passwordController = TextEditingController();
  final _fromNameController = TextEditingController(text: 'vasX Notification Portal');

  bool _isLoading = false;

  @override
  void dispose() {
    _hostController.dispose();
    _portController.dispose();
    _usernameController.dispose();
    _passwordController.dispose();
    _fromNameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxFormCard (Form)')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Center(
          child: ConstrainedBox(
            constraints: const BoxConstraints(maxWidth: 540),
            child: VasxFormCard(
              title: 'Email Credentials (SMTP)',
              subtitle: 'Configure email server for OTP delivery',
              headerIcon: Icons.email_outlined,
              badgeColor: const Color(0xFFEEF2FF),
              badgeIconColor: VasxColors.primary,
              isLoading: _isLoading,
              fields: [
                VasxFormFieldConfig(
                  label: 'SMTP Host',
                  hintText: 'e.g. smtp.gmail.com',
                  controller: _hostController,
                  prefixIcon: Icons.dns_outlined,
                ),
                VasxFormFieldConfig(
                  label: 'SMTP Port',
                  hintText: '587',
                  controller: _portController,
                  prefixIcon: Icons.tag_outlined,
                  keyboardType: TextInputType.number,
                ),
                VasxFormFieldConfig(
                  label: 'Username / Email',
                  hintText: 'user@domain.com',
                  controller: _usernameController,
                  prefixIcon: Icons.person_outline_rounded,
                  keyboardType: TextInputType.emailAddress,
                ),
                VasxFormFieldConfig(
                  label: 'App Password',
                  hintText: 'Current: (leave blank to keep)',
                  controller: _passwordController,
                  prefixIcon: Icons.lock_outline_rounded,
                  obscureText: true,
                ),
                VasxFormFieldConfig(
                  label: 'From Name',
                  hintText: 'ID Card Portal',
                  controller: _fromNameController,
                  prefixIcon: Icons.badge_outlined,
                ),
              ],
              submitButtonLabel: 'Save Credentials',
              onSubmit: () async {
                setState(() => _isLoading = true);
                await Future.delayed(const Duration(seconds: 1));
                if (!context.mounted) return;
                setState(() => _isLoading = false);
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Credentials saved successfully!')),
                );
              },
            ),
          ),
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// AI Assistant SearchBar Example
// ─────────────────────────────────────────────
class AiSearchBarExample extends StatefulWidget {
  const AiSearchBarExample({super.key});

  @override
  State<AiSearchBarExample> createState() => _AiSearchBarExampleState();
}

class _AiSearchBarExampleState extends State<AiSearchBarExample> {
  String _submittedQuery = '';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxAiSearchBar')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 48),
        child: Center(
          child: Column(
            children: [
              VasxAiSearchBar(
                title: 'What are you looking for today?',
                subtitle: 'Ask anything about your students & staff',
                hintText: 'Search settings, students, staff...',
                attachmentItems: [
                  VasxAiAttachmentItem(
                    label: 'Add Photos',
                    icon: Icons.add_a_photo_outlined,
                    onTap: () {
                      if (!mounted) return;
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Add Photos tapped')),
                      );
                    },
                  ),
                  VasxAiAttachmentItem(
                    label: 'Students',
                    icon: Icons.people_outline_rounded,
                    onTap: () {
                      if (!mounted) return;
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Students category tapped')),
                      );
                    },
                  ),
                  VasxAiAttachmentItem(
                    label: 'Staffs',
                    icon: Icons.badge_outlined,
                    onTap: () {
                      if (!mounted) return;
                      ScaffoldMessenger.of(context).showSnackBar(
                        const SnackBar(content: Text('Staffs category tapped')),
                      );
                    },
                  ),
                ],
                onSubmitted: (query) {
                  setState(() => _submittedQuery = query);
                },
              ),
              if (_submittedQuery.isNotEmpty) ...[
                const SizedBox(height: 36),
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: Colors.white,
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: VasxColors.borderLight),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Icon(Icons.auto_awesome, color: VasxColors.primary, size: 20),
                      const SizedBox(width: 10),
                      Text(
                        'Searching for: "$_submittedQuery"',
                        style: const TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.w600,
                          color: VasxColors.textPrimary,
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Payment Confirmation Example
// ─────────────────────────────────────────────
class PaymentConfirmationExample extends StatefulWidget {
  const PaymentConfirmationExample({super.key});

  @override
  State<PaymentConfirmationExample> createState() =>
      _PaymentConfirmationExampleState();
}

class _PaymentConfirmationExampleState
    extends State<PaymentConfirmationExample> {
  double? _lastPaidAmount;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxPaymentConfirmationDialog')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Center(
          child: Column(
            children: [
              Container(
                padding: const EdgeInsets.all(24),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(16),
                  border: Border.all(color: VasxColors.borderLight),
                ),
                child: Column(
                  children: [
                    const Icon(Icons.shopping_cart_checkout_rounded,
                        size: 48, color: VasxColors.primary),
                    const SizedBox(height: 12),
                    const Text(
                      'Supermarket Billing Checkout',
                      style: TextStyle(
                        fontSize: 18,
                        fontWeight: FontWeight.bold,
                        color: VasxColors.textPrimary,
                      ),
                    ),
                    const SizedBox(height: 6),
                    Text(
                      'Tap below to trigger the payment confirmation dialog.',
                      style: TextStyle(fontSize: 13, color: Colors.grey[600]),
                      textAlign: TextAlign.center,
                    ),
                    const SizedBox(height: 20),
                    VasxButton(
                      label: 'Open Payment Dialog',
                      icon: Icons.receipt_long_rounded,
                      onPressed: () async {
                        final paid = await showVasxPaymentConfirmationDialog(
                          context: context,
                          title: 'Supermarket Billing Details',
                          description: 'FreshMart Checkout (5 items)',
                          totalAmount: 2490.00,
                          alreadyPaidAmount: 490.00,
                          currencySymbol: '₹',
                          breakdownItems: const [
                            VasxPaymentConfirmationItem(
                              label: 'Fresh Organic Milk 2L',
                              amount: 180.00,
                            ),
                            VasxPaymentConfirmationItem(
                              label: 'Whole Wheat Bread',
                              amount: 60.00,
                            ),
                            VasxPaymentConfirmationItem(
                              label: 'Extra Virgin Olive Oil 1L',
                              amount: 850.00,
                            ),
                            VasxPaymentConfirmationItem(
                              label: 'Dark Chocolate Bar 100g',
                              amount: 200.00,
                            ),
                            VasxPaymentConfirmationItem(
                              label: 'Organic Wildflower Honey 500g',
                              amount: 700.00,
                            ),
                          ],
                        );
                        if (paid != null) {
                          setState(() => _lastPaidAmount = paid);
                          if (!context.mounted) return;
                          ScaffoldMessenger.of(context).showSnackBar(
                            SnackBar(
                              content: Text('Payment of ₹$paid confirmed successfully!'),
                            ),
                          );
                        }
                      },
                    ),
                  ],
                ),
              ),
              if (_lastPaidAmount != null) ...[
                const SizedBox(height: 24),
                Container(
                  padding: const EdgeInsets.all(16),
                  decoration: BoxDecoration(
                    color: const Color(0xFFDCFCE7),
                    borderRadius: BorderRadius.circular(12),
                    border: Border.all(color: const Color(0xFF86EFAC)),
                  ),
                  child: Row(
                    mainAxisSize: MainAxisSize.min,
                    children: [
                      const Icon(Icons.check_circle_rounded,
                          color: Color(0xFF16A34A), size: 22),
                      const SizedBox(width: 10),
                      Text(
                        'Last Payment Received: ₹${_lastPaidAmount!.toStringAsFixed(2)}',
                        style: const TextStyle(
                          fontSize: 15,
                          fontWeight: FontWeight.w700,
                          color: Color(0xFF15803D),
                        ),
                      ),
                    ],
                  ),
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Alert Banners Example
// ─────────────────────────────────────────────
class AlertExample extends StatefulWidget {
  const AlertExample({super.key});

  @override
  State<AlertExample> createState() => _AlertExampleState();
}

class _AlertExampleState extends State<AlertExample> {
  bool _showGreenAlert = true;
  bool _showYellowAlert = true;
  bool _showRedAlert = true;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: VasxColors.surface,
      appBar: AppBar(title: const Text('VasxAlert & Animated Toast')),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            const Text(
              'Interactive Top-Right Alert Toasts (2s Auto-Hide)',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 8),
            Text(
              'Click any button below to trigger a smooth top-right animated alert toast that auto-hides after 2 seconds.',
              style: TextStyle(fontSize: 13, color: Colors.grey[600]),
            ),
            const SizedBox(height: 16),
            Wrap(
              spacing: 12,
              runSpacing: 12,
              children: [
                VasxButton(
                  label: 'Success Toast (Green)',
                  icon: Icons.check_circle_rounded,
                  variant: VasxButtonVariant.primary,
                  primaryColor: const Color(0xFF15803D),
                  onPressed: () {
                    showVasxAlertToast(
                      context: context,
                      title: 'Logout Successful',
                      message: 'See you soon!',
                      type: VasxAlertType.success,
                      duration: const Duration(seconds: 2),
                    );
                  },
                ),
                VasxButton(
                  label: 'Warning Toast (Yellow)',
                  icon: Icons.warning_amber_rounded,
                  variant: VasxButtonVariant.primary,
                  primaryColor: const Color(0xFFD97706),
                  onPressed: () {
                    showVasxAlertToast(
                      context: context,
                      title: 'Storage Warning',
                      message: 'Cloud storage at 85% capacity.',
                      type: VasxAlertType.warning,
                      duration: const Duration(seconds: 2),
                    );
                  },
                ),
                VasxButton(
                  label: 'Error Toast (Red)',
                  icon: Icons.error_outline_rounded,
                  variant: VasxButtonVariant.primary,
                  primaryColor: const Color(0xFFDC2626),
                  onPressed: () {
                    showVasxAlertToast(
                      context: context,
                      title: 'Database Connection Failed',
                      message: 'Unable to reach primary server.',
                      type: VasxAlertType.error,
                      duration: const Duration(seconds: 2),
                    );
                  },
                ),
              ],
            ),
            const SizedBox(height: 36),
            const Divider(),
            const SizedBox(height: 24),
            const Text(
              'Solid Inline Alert Banners (Reference Design)',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            if (_showGreenAlert) ...[
              VasxAlert(
                title: 'Logout Successful',
                message: 'See you soon!',
                type: VasxAlertType.success,
                variant: VasxAlertVariant.solid,
                onDismiss: () => setState(() => _showGreenAlert = false),
              ),
              const SizedBox(height: 16),
            ],
            if (_showYellowAlert) ...[
              VasxAlert(
                title: 'Storage Warning',
                message: 'Your allocated cloud storage has reached 85% capacity.',
                type: VasxAlertType.warning,
                variant: VasxAlertVariant.solid,
                onDismiss: () => setState(() => _showYellowAlert = false),
              ),
              const SizedBox(height: 16),
            ],
            if (_showRedAlert) ...[
              VasxAlert(
                title: 'Database Connection Failed',
                message: 'Unable to synchronize with primary replica. Retrying in 10s.',
                type: VasxAlertType.error,
                variant: VasxAlertVariant.solid,
                onDismiss: () => setState(() => _showRedAlert = false),
              ),
              const SizedBox(height: 16),
            ],
            if (!_showGreenAlert || !_showYellowAlert || !_showRedAlert) ...[
              ElevatedButton.icon(
                icon: const Icon(Icons.refresh_rounded),
                label: const Text('Restore Dismissed Banners'),
                onPressed: () {
                  setState(() {
                    _showGreenAlert = true;
                    _showYellowAlert = true;
                    _showRedAlert = true;
                  });
                },
              ),
              const SizedBox(height: 16),
            ],
            const SizedBox(height: 24),
            const Text(
              'Soft Outline Alert Banners',
              style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
            ),
            const SizedBox(height: 16),
            const VasxAlert(
              title: 'Success: Payment Verified',
              message: 'Transaction #TXN-90218 completed.',
              type: VasxAlertType.success,
              variant: VasxAlertVariant.soft,
            ),
            const SizedBox(height: 12),
            const VasxAlert(
              title: 'Caution: Unsaved Modifications',
              message: 'You have pending changes that have not been published.',
              type: VasxAlertType.warning,
              variant: VasxAlertVariant.soft,
            ),
            const SizedBox(height: 12),
            const VasxAlert(
              title: 'Error: Authentication Timeout',
              message: 'Your session has expired. Please log in again.',
              type: VasxAlertType.error,
              variant: VasxAlertVariant.soft,
            ),
          ],
        ),
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Side Menu (E-Commerce) Example
// ─────────────────────────────────────────────
class SideMenuExample extends StatefulWidget {
  const SideMenuExample({super.key});

  @override
  State<SideMenuExample> createState() => _SideMenuExampleState();
}

class _SideMenuExampleState extends State<SideMenuExample> {
  String _selectedId = 'dashboard';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('VasxSideMenu (Hover to Expand)')),
      body: Row(
        children: [
          VasxSideMenu(
            brandName: 'Test Shop',
            selectedId: _selectedId,
            expandOnHover: true,
            onItemSelected: (id) {
              setState(() => _selectedId = id);
              if (id == 'logout') {
                ScaffoldMessenger.of(context).showSnackBar(
                  const SnackBar(content: Text('Logout clicked')),
                );
              }
            },
            items: const [
              VasxSideMenuItem(
                id: 'dashboard',
                label: 'Dashboard',
                icon: Icons.grid_view_rounded,
              ),
              VasxSideMenuItem(
                id: 'orders',
                label: 'My Orders',
                icon: Icons.shopping_bag_outlined,
                badgeText: '5',
              ),
              VasxSideMenuItem(
                id: 'products',
                label: 'Products & Catalog',
                icon: Icons.inventory_2_outlined,
                subItems: [
                  VasxSideMenuItem(
                    id: 'all_products',
                    label: 'All Products',
                    icon: Icons.list_alt_rounded,
                  ),
                  VasxSideMenuItem(
                    id: 'add_product',
                    label: 'Add Product',
                    icon: Icons.add_box_outlined,
                  ),
                  VasxSideMenuItem(
                    id: 'categories',
                    label: 'Categories',
                    icon: Icons.category_outlined,
                  ),
                ],
              ),
              VasxSideMenuItem(
                id: 'customers',
                label: 'Customers',
                icon: Icons.people_outline_rounded,
              ),
              VasxSideMenuItem(
                id: 'analytics',
                label: 'Sales & Analytics',
                icon: Icons.insights_rounded,
              ),
              VasxSideMenuItem(
                id: 'coupons',
                label: 'Discounts & Offers',
                icon: Icons.local_offer_outlined,
              ),
              VasxSideMenuItem(
                id: 'bulk_upload',
                label: 'Bulk Upload',
                icon: Icons.upload_file_outlined,
              ),
              VasxSideMenuItem(
                id: 'billing',
                label: 'Payments & Billing',
                icon: Icons.account_balance_wallet_outlined,
              ),
            ],
            bottomItems: const [
              VasxSideMenuItem(
                id: 'settings',
                label: 'Store Settings',
                icon: Icons.settings_outlined,
              ),
              VasxSideMenuItem(
                id: 'logout',
                label: 'Logout',
                icon: Icons.logout_rounded,
                isDestructive: true,
              ),
            ],
          ),
          Expanded(
            child: Container(
              color: VasxColors.surface,
              padding: const EdgeInsets.all(32),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    'Selected Section: ${_selectedId.toUpperCase()}',
                    style: const TextStyle(
                      fontSize: 20,
                      fontWeight: FontWeight.bold,
                      color: VasxColors.textPrimary,
                    ),
                  ),
                  const SizedBox(height: 12),
                  const Text(
                    'Hover your mouse over the left sidebar to experience the smooth expansion from compact (72px) to full (250px) width mode!',
                    style: TextStyle(fontSize: 14, color: Colors.grey),
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }
}

// ─────────────────────────────────────────────
// Mobile Bottom NavBar Example
// ─────────────────────────────────────────────
class BottomNavBarExample extends StatefulWidget {
  const BottomNavBarExample({super.key});

  @override
  State<BottomNavBarExample> createState() => _BottomNavBarExampleState();
}

class _BottomNavBarExampleState extends State<BottomNavBarExample> {
  String _selectedTab = 'dashboard';

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF1F5F9),
      appBar: AppBar(title: const Text('VasxMobileBottomNavBar')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Container(
              padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
              decoration: BoxDecoration(
                color: Colors.white,
                borderRadius: BorderRadius.circular(16),
                boxShadow: [
                  BoxShadow(
                    color: Colors.black.withValues(alpha: 0.05),
                    blurRadius: 10,
                  ),
                ],
              ),
              child: Column(
                children: [
                  const Icon(Icons.phone_android_rounded, size: 48, color: VasxColors.primary),
                  const SizedBox(height: 12),
                  Text(
                    'Active Tab: ${_selectedTab.toUpperCase()}',
                    style: const TextStyle(
                      fontSize: 18,
                      fontWeight: FontWeight.bold,
                      color: VasxColors.textPrimary,
                    ),
                  ),
                  const SizedBox(height: 4),
                  const Text(
                    'Tap any icon in the floating bottom navigation bar below.',
                    style: TextStyle(fontSize: 13, color: Colors.grey),
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
      bottomNavigationBar: VasxMobileBottomNavBar(
        selectedId: _selectedTab,
        onItemSelected: (id) => setState(() => _selectedTab = id),
        items: const [
          VasxBottomNavItem(
            id: 'dashboard',
            label: 'Dashboard',
            icon: Icons.grid_view_rounded,
          ),
          VasxBottomNavItem(
            id: 'orders',
            label: 'My Orders',
            icon: Icons.shopping_bag_outlined,
            badgeText: '3',
          ),
          VasxBottomNavItem(
            id: 'students',
            label: 'Customers',
            icon: Icons.people_outline_rounded,
          ),
          VasxBottomNavItem(
            id: 'staffs',
            label: 'Staffs',
            icon: Icons.groups_outlined,
          ),
          VasxBottomNavItem(
            id: 'upload',
            label: 'Bulk Upload',
            icon: Icons.upload_file_outlined,
          ),
          VasxBottomNavItem(
            id: 'settings',
            label: 'Settings',
            icon: Icons.manage_accounts_outlined,
          ),
        ],
      ),
    );
  }
}
2
likes
150
points
82
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

vasX UI — a collection of beautiful, reusable Flutter widgets including smart dropdowns, date pickers, multi-step wizards, animated popup menus, and responsive data tables. Built for production-grade Flutter apps.

License

MIT (license)

Dependencies

fl_chart, flutter, intl

More

Packages that depend on vasx_ui