minilo_design_system 0.1.3 copy "minilo_design_system: ^0.1.3" to clipboard
minilo_design_system: ^0.1.3 copied to clipboard

Official Minilo Design System component library for Flutter.

example/lib/main.dart

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

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

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

  static final List<WidgetCatalogEntry> entries = buildCatalogEntries();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Minilo Flutter Design System',
      debugShowCheckedModeBanner: false,
      theme: miniloThemeData(),
      darkTheme: miniloThemeData(brightness: Brightness.dark),
      home: WidgetCatalogHome(entries: entries),
      onGenerateRoute: (settings) {
        final name = settings.name;
        if (name == null || name == '/') {
          return MaterialPageRoute<void>(
            builder: (_) => WidgetCatalogHome(entries: entries),
          );
        }

        if (name == '/visual-grid') {
          return MaterialPageRoute<void>(
            builder: (_) => WidgetVisualGridPage(entries: entries),
            settings: settings,
          );
        }

        for (final entry in entries) {
          if (entry.route == name) {
            return MaterialPageRoute<void>(
              builder: (_) => WidgetPreviewPage(entry: entry),
              settings: settings,
            );
          }
        }

        return MaterialPageRoute<void>(
          builder: (_) => WidgetCatalogHome(entries: entries),
        );
      },
    );
  }
}

typedef WidgetPreviewBuilder = Widget Function(BuildContext context);

@immutable
class WidgetCatalogEntry {
  const WidgetCatalogEntry({
    required this.route,
    required this.group,
    required this.title,
    required this.builder,
    this.description,
    this.previewSize,
  });

  final String route;
  final String group;
  final String title;
  final WidgetPreviewBuilder builder;
  final String? description;
  final Size? previewSize;
}

class WidgetCatalogHome extends StatefulWidget {
  const WidgetCatalogHome({super.key, required this.entries});

  final List<WidgetCatalogEntry> entries;

  @override
  State<WidgetCatalogHome> createState() => _WidgetCatalogHomeState();
}

class _WidgetCatalogHomeState extends State<WidgetCatalogHome> {
  final TextEditingController _searchController = TextEditingController();

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

  @override
  Widget build(BuildContext context) {
    final minilo = context.minilo;
    final query = _searchController.text.trim().toLowerCase();

    final filtered = widget.entries.where((entry) {
      if (query.isEmpty) {
        return true;
      }
      return entry.title.toLowerCase().contains(query) ||
          entry.group.toLowerCase().contains(query);
    }).toList();

    final groupOrder = <String>[
      'Buttons',
      'Inputs',
      'Selection',
      'Cards',
      'Feedback',
      'Data Display',
      'Navigation',
      'Tabs',
      'Stepper',
      'Search',
      'Pagination',
      'Layout',
      'Charts',
      'Containers',
      'More',
    ];

    return Scaffold(
      appBar: AppBar(title: const Text('Minilo Widget Catalog')),
      body: SafeArea(
        child: ListView(
          padding: EdgeInsets.all(minilo.spacing.s4),
          children: [
            MiniloSectionHeader(
              eyebrow: 'Minilo Flutter',
              title: 'Component Showcase',
              description:
                  'Open any widget below to see a dedicated visual preview page.',
            ),
            const SizedBox(height: 16),
            TextField(
              controller: _searchController,
              onChanged: (_) => setState(() {}),
              decoration: InputDecoration(
                hintText: 'Search widgets...',
                prefixIcon: const Icon(Icons.search),
                border: OutlineInputBorder(
                  borderRadius: BorderRadius.circular(8),
                ),
              ),
            ),
            const SizedBox(height: 12),
            Align(
              alignment: Alignment.centerLeft,
              child: OutlinedButton.icon(
                onPressed: () =>
                    Navigator.of(context).pushNamed('/visual-grid'),
                icon: const Icon(Icons.grid_view_outlined),
                label: const Text('Visual Grid Preview'),
              ),
            ),
            const SizedBox(height: 16),
            for (final group in groupOrder) ...[
              if (filtered.any((entry) => entry.group == group)) ...[
                Text(
                  group,
                  style: Theme.of(context).textTheme.titleMedium,
                ),
                const SizedBox(height: 8),
                ...filtered.where((entry) => entry.group == group).map(
                      (entry) => Card(
                        margin: const EdgeInsets.only(bottom: 8),
                        child: ListTile(
                          title: Text(entry.title),
                          subtitle: entry.description == null
                              ? null
                              : Text(entry.description!),
                          trailing: const Icon(Icons.chevron_right),
                          onTap: () =>
                              Navigator.of(context).pushNamed(entry.route),
                        ),
                      ),
                    ),
                const SizedBox(height: 8),
              ],
            ],
          ],
        ),
      ),
    );
  }
}

class WidgetVisualGridPage extends StatelessWidget {
  const WidgetVisualGridPage({super.key, required this.entries});

  final List<WidgetCatalogEntry> entries;

  @override
  Widget build(BuildContext context) {
    final minilo = context.minilo;

    final groups = <String, List<WidgetCatalogEntry>>{};
    for (final entry in entries) {
      groups.putIfAbsent(entry.group, () => <WidgetCatalogEntry>[]).add(entry);
    }

    return Scaffold(
      appBar: AppBar(title: const Text('Visual Grid Preview')),
      body: SafeArea(
        child: ListView(
          padding: EdgeInsets.all(minilo.spacing.s4),
          children: groups.entries.map((group) {
            return Padding(
              padding: const EdgeInsets.only(bottom: 24),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    group.key,
                    style: Theme.of(context).textTheme.titleMedium,
                  ),
                  const SizedBox(height: 10),
                  Wrap(
                    spacing: 12,
                    runSpacing: 12,
                    children: group.value.map((entry) {
                      return _WidgetPreviewTile(entry: entry);
                    }).toList(),
                  ),
                ],
              ),
            );
          }).toList(),
        ),
      ),
    );
  }
}

class _WidgetPreviewTile extends StatelessWidget {
  const _WidgetPreviewTile({required this.entry});

  final WidgetCatalogEntry entry;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      borderRadius: BorderRadius.circular(8),
      onTap: () => Navigator.of(context).pushNamed(entry.route),
      child: Container(
        width: 340,
        padding: const EdgeInsets.all(12),
        decoration: BoxDecoration(
          color: context.minilo.colors.surface,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: context.minilo.colors.border),
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text(
              entry.title,
              style: Theme.of(context).textTheme.labelLarge,
            ),
            const SizedBox(height: 10),
            _PreviewCanvas(entry: entry),
          ],
        ),
      ),
    );
  }
}

class WidgetPreviewPage extends StatelessWidget {
  const WidgetPreviewPage({super.key, required this.entry});

  final WidgetCatalogEntry entry;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(entry.title)),
      body: SafeArea(
        child: ListView(
          padding: const EdgeInsets.all(16),
          children: [
            Text(
              entry.group,
              style: Theme.of(context).textTheme.labelLarge,
            ),
            if (entry.description != null) ...[
              const SizedBox(height: 6),
              Text(
                entry.description!,
                style: Theme.of(context).textTheme.bodyMedium,
              ),
            ],
            const SizedBox(height: 16),
            _PreviewCanvas(entry: entry),
          ],
        ),
      ),
    );
  }
}

class _PreviewCanvas extends StatelessWidget {
  const _PreviewCanvas({required this.entry});

  final WidgetCatalogEntry entry;

  @override
  Widget build(BuildContext context) {
    final size = entry.previewSize;
    final previewChild = entry.builder(context);

    final Widget previewViewport;
    if (size == null) {
      previewViewport = SingleChildScrollView(
        scrollDirection: Axis.horizontal,
        child: previewChild,
      );
    } else {
      previewViewport = SizedBox(
        width: size.width,
        height: size.height,
        child: ClipRect(
          child: SingleChildScrollView(
            scrollDirection: Axis.vertical,
            child: SingleChildScrollView(
              scrollDirection: Axis.horizontal,
              child: ConstrainedBox(
                constraints: BoxConstraints(
                  minWidth: size.width,
                  maxWidth: size.width,
                  minHeight: size.height,
                ),
                child: Align(
                  alignment: Alignment.topLeft,
                  child: previewChild,
                ),
              ),
            ),
          ),
        ),
      );
    }

    return Container(
      padding: const EdgeInsets.all(16),
      decoration: BoxDecoration(
        color: context.minilo.colors.surface,
        borderRadius: BorderRadius.circular(8),
        border: Border.all(color: context.minilo.colors.border),
      ),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          if (size != null)
            Padding(
              padding: const EdgeInsets.only(bottom: 8),
              child: Text(
                '${size.width.toInt()} x ${size.height.toInt()} px',
                style: Theme.of(context).textTheme.bodySmall,
              ),
            ),
          previewViewport,
        ],
      ),
    );
  }
}

List<WidgetCatalogEntry> buildCatalogEntries() {
  return <WidgetCatalogEntry>[
    WidgetCatalogEntry(
      route: '/buttons/primary',
      group: 'Buttons',
      title: 'Primary Button',
      previewSize: const Size(136, 52),
      builder: (_) => MiniloPrimaryButton(label: 'Add New', onPressed: () {}),
    ),
    WidgetCatalogEntry(
      route: '/buttons/secondary',
      group: 'Buttons',
      title: 'Secondary Button',
      previewSize: const Size(136, 52),
      builder: (_) => MiniloSecondaryButton(
        label: 'Add New',
        icon: const Icon(Icons.add),
        onPressed: () {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/buttons/tertiary',
      group: 'Buttons',
      title: 'Tertiary Button',
      previewSize: const Size(136, 52),
      builder: (_) => MiniloTertiaryButton(
        label: 'Add New',
        icon: const Icon(Icons.add),
        onPressed: () {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/buttons/tile',
      group: 'Buttons',
      title: 'Tile Button',
      previewSize: const Size(205, 64),
      builder: (_) => MiniloTileButton(
        width: 205,
        label: 'Go to profile',
        leading: const Icon(Icons.person_outline),
        onTap: () {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/text-field',
      group: 'Inputs',
      title: 'Text Field',
      previewSize: const Size(343, 52),
      builder: (_) => const MiniloTextField(
        label: 'Account Name',
        placeholder: 'Default State Input',
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/dropdown',
      group: 'Inputs',
      title: 'Dropdown Field',
      previewSize: const Size(343, 76),
      builder: (_) => MiniloDropdownField<String>(
        label: 'Role',
        placeholder: 'Select option',
        options: const [
          MiniloDropdownOption(value: 'designer', label: 'Designer'),
          MiniloDropdownOption(value: 'developer', label: 'Developer'),
        ],
        onChanged: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/text-field-tooltip',
      group: 'Inputs',
      title: 'Text Field With Tooltip',
      previewSize: const Size(343, 52),
      builder: (_) => const MiniloTextFieldWithTooltip(
        label: 'Account Name',
        placeholder: 'Filled State Input',
        tooltipMessage: 'Tooltip on top',
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/text-area',
      group: 'Inputs',
      title: 'Text Area Field',
      previewSize: const Size(343, 108),
      builder: (_) => const MiniloTextAreaField(),
    ),
    WidgetCatalogEntry(
      route: '/inputs/search-field',
      group: 'Inputs',
      title: 'Search Field',
      previewSize: const Size(343, 48),
      builder: (_) => const MiniloSearchField(),
    ),
    WidgetCatalogEntry(
      route: '/inputs/search-desktop',
      group: 'Inputs',
      title: 'Search Bar Desktop',
      previewSize: const Size(260, 48),
      builder: (_) => const MiniloSearchBarDesktop(
        state: MiniloSearchBarDesktopState.active,
        hintText: 'Typing',
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/toggle',
      group: 'Inputs',
      title: 'Toggle Switch',
      previewSize: const Size(220, 72),
      builder: (_) => const MiniloToggleSwitch(
        width: 220,
        label: 'Toggle',
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/filter-button',
      group: 'Inputs',
      title: 'Filter Button',
      previewSize: const Size(48, 48),
      builder: (_) => const MiniloFilterIconButton(active: true, count: 4),
    ),
    WidgetCatalogEntry(
      route: '/inputs/filter-chips',
      group: 'Inputs',
      title: 'Filter Chips',
      previewSize: const Size(386, 28),
      builder: (_) => MiniloFilterChips(
        items: const [
          MiniloFilterChipItem(label: 'All', count: 37, selected: true),
          MiniloFilterChipItem(label: 'Approved', count: 30),
          MiniloFilterChipItem(label: 'Pending', count: 6),
          MiniloFilterChipItem(label: 'Rejected', count: 1),
        ],
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/document-selection',
      group: 'Inputs',
      title: 'Document Selection',
      previewSize: const Size(343, 195),
      builder: (_) =>
          const MiniloDocumentSelection(fileName: 'Name of the Doc.PDF'),
    ),
    WidgetCatalogEntry(
      route: '/inputs/document-upload',
      group: 'Inputs',
      title: 'Document Upload',
      previewSize: const Size(420, 108),
      builder: (_) => const MiniloDocumentUpload(
        state: MiniloDocumentUploadState.upload,
      ),
    ),
    WidgetCatalogEntry(
      route: '/inputs/document-uploaded',
      group: 'Inputs',
      title: 'Document Uploaded State',
      previewSize: const Size(420, 60),
      builder: (_) => const MiniloDocumentUpload(
        state: MiniloDocumentUploadState.uploaded,
        fileName: 'Uploaded file.pdf',
      ),
    ),
    WidgetCatalogEntry(
      route: '/selection/checkbox',
      group: 'Selection',
      title: 'Checkbox',
      previewSize: const Size(52, 20),
      builder: (_) => const Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          MiniloCheckbox(value: true),
          SizedBox(width: 12),
          MiniloCheckbox(value: false),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/selection/radio',
      group: 'Selection',
      title: 'Radio',
      previewSize: const Size(52, 20),
      builder: (_) => const Row(
        mainAxisSize: MainAxisSize.min,
        children: [
          MiniloRadio(selected: true),
          SizedBox(width: 12),
          MiniloRadio(selected: false),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/selection/radio-with-text',
      group: 'Selection',
      title: 'Radio With Text',
      previewSize: const Size(180, 20),
      builder: (_) => const MiniloRadioWithText<String>(
        label: 'Radio with Text',
        value: 'option-1',
        groupValue: 'option-1',
      ),
    ),
    WidgetCatalogEntry(
      route: '/cards/large',
      group: 'Cards',
      title: 'Card Large',
      previewSize: const Size(343, 368),
      builder: (_) => MiniloCardLarge(
        title: 'Candidate Profile',
        status: 'Approved',
        details: const [
          MiniloCardDetail(label: 'Name', value: 'Jane Cooper'),
          MiniloCardDetail(label: 'Experience', value: '8 years'),
          MiniloCardDetail(label: 'Location', value: 'Bengaluru'),
          MiniloCardDetail(label: 'Skills', value: 'Flutter, Dart'),
        ],
        onPrimaryAction: () {},
        onSecondaryAction: () {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/cards/large-vertical-list',
      group: 'Cards',
      title: 'Card Large Vertical List',
      previewSize: const Size(323, 203),
      builder: (_) => MiniloCardLargeVerticalList(
        item: const MiniloVerticalListItem(
          title: 'Coin',
          lines: ['Lorem ipsum dolor sit amet', 'Metus faucibus condimentum'],
          status: 'Approved',
        ),
        onApprove: () {},
        onReject: () {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/cards/small',
      group: 'Cards',
      title: 'Card Small',
      previewSize: const Size(194, 176),
      builder: (_) => const MiniloCardSmall(
        headline: 'Senior Flutter Engineer',
        text: 'Design and build scalable app architecture.',
        icon: Icon(Icons.work_outline),
      ),
    ),
    WidgetCatalogEntry(
      route: '/cards/xs',
      group: 'Cards',
      title: 'Card XS',
      previewSize: const Size(343, 104),
      builder: (_) => const MiniloCardXs(
        title: 'Feed Update',
        subtitle: 'New dashboard widgets released this week.',
      ),
    ),
    WidgetCatalogEntry(
      route: '/cards/item',
      group: 'Cards',
      title: 'Item Card',
      previewSize: const Size(323, 203),
      builder: (_) => const MiniloItemCard(),
    ),
    WidgetCatalogEntry(
      route: '/cards/profile',
      group: 'Cards',
      title: 'Profile Card',
      previewSize: const Size(343, 284),
      builder: (_) => const MiniloProfileCard(),
    ),
    WidgetCatalogEntry(
      route: '/cards/accordion-list',
      group: 'Cards',
      title: 'Accordion List',
      previewSize: const Size(343, 112),
      builder: (_) => const MiniloAccordionList(
        items: [
          MiniloAccordionListItem(
            title: 'Accordion List 1',
            content: Text('Accordion content one'),
          ),
          MiniloAccordionListItem(
            title: 'Accordion List 2',
            content: Text('Accordion content two'),
          ),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/feedback/alert-banner',
      group: 'Feedback',
      title: 'Alert Banner',
      previewSize: const Size(375, 80),
      builder: (_) => const SizedBox(
        width: 375,
        child: MiniloAlertBanner(
          title: 'System notice',
          message: 'Your profile updates were synced successfully.',
          variant: MiniloAlertVariant.success,
          dismissible: true,
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/feedback/toast',
      group: 'Feedback',
      title: 'Toast',
      previewSize: const Size(349, 216),
      builder: (_) => const Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          MiniloToast(
              message: 'Success message', type: MiniloToastType.success),
          SizedBox(height: 8),
          MiniloToast(
              message: 'Warning message', type: MiniloToastType.warning),
          SizedBox(height: 8),
          MiniloToast(
              message: 'Notification message', type: MiniloToastType.notify),
          SizedBox(height: 8),
          MiniloToast(message: 'Error message', type: MiniloToastType.error),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/data/badge',
      group: 'Data Display',
      title: 'Badge',
      previewSize: const Size(280, 56),
      builder: (_) => const Wrap(
        spacing: 8,
        runSpacing: 8,
        children: [
          MiniloBadge(label: 'Neutral'),
          MiniloBadge(label: 'Info', tone: MiniloBadgeTone.info, filled: true),
          MiniloBadge(
              label: 'Success', tone: MiniloBadgeTone.success, filled: true),
          MiniloBadge(
              label: 'Warning', tone: MiniloBadgeTone.warning, filled: true),
          MiniloBadge(
              label: 'Error', tone: MiniloBadgeTone.error, filled: true),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/data/label',
      group: 'Data Display',
      title: 'Label',
      previewSize: const Size(280, 24),
      builder: (_) => const Wrap(
        spacing: 8,
        runSpacing: 8,
        children: [
          MiniloLabel(text: 'Green', tone: MiniloLabelTone.green),
          MiniloLabel(text: 'Red', tone: MiniloLabelTone.red),
          MiniloLabel(text: 'Yellow', tone: MiniloLabelTone.yellow),
          MiniloLabel(text: 'Blue', tone: MiniloLabelTone.blue),
          MiniloLabel(text: 'Grey', tone: MiniloLabelTone.grey),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/data/stat-card',
      group: 'Data Display',
      title: 'Stat Card',
      previewSize: const Size(343, 184),
      builder: (_) => const MiniloStatCard(),
    ),
    WidgetCatalogEntry(
      route: '/navigation/page-back',
      group: 'Navigation',
      title: 'Page Back Link',
      previewSize: const Size(81, 38),
      builder: (_) => MiniloPageBackLink(onTap: () {}),
    ),
    WidgetCatalogEntry(
      route: '/navigation/breadcrumbs',
      group: 'Navigation',
      title: 'Breadcrumbs',
      previewSize: const Size(189, 32),
      builder: (_) => MiniloBreadcrumbs(
        items: [
          MiniloBreadcrumbItem(label: 'Home', onTap: () {}),
          MiniloBreadcrumbItem(label: 'Docs', onTap: () {}),
          const MiniloBreadcrumbItem(label: 'Buttons', isCurrent: true),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/navigation/app-bar',
      group: 'Navigation',
      title: 'App Bar',
      previewSize: const Size(375, 100),
      builder: (_) => const MiniloAppBar(),
    ),
    WidgetCatalogEntry(
      route: '/navigation/app-bar-alt',
      group: 'Navigation',
      title: 'App Bar Alt',
      previewSize: const Size(375, 100),
      builder: (_) => const MiniloAppBarAlt(title: 'My Profile'),
    ),
    WidgetCatalogEntry(
      route: '/navigation/desktop-header',
      group: 'Navigation',
      title: 'Desktop Header',
      previewSize: const Size(1440, 80),
      builder: (_) => const MiniloDesktopHeader(
        state: MiniloDesktopHeaderState.open,
        title: 'Logo',
        profileName: 'User Name',
        profileEmail: 'email@example.com',
        menuChips: [
          MiniloHeaderMenuChip(icon: Icons.language_outlined),
          MiniloHeaderMenuChip(icon: Icons.notifications_none, badgeCount: 2),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/navigation/bottom-nav',
      group: 'Navigation',
      title: 'Bottom Nav Bar',
      previewSize: const Size(375, 56),
      builder: (_) => SizedBox(
        width: 375,
        child: MiniloBottomNavBar.defaultTabs(
          currentIndex: 1,
          onTap: (_) {},
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/navigation/mobile-bottom-nav-atom',
      group: 'Navigation',
      title: 'Mobile Bottom Nav Atom',
      previewSize: const Size(375, 56),
      builder: (_) => const MiniloMobileBottomNavAtom(
        items: [
          MiniloMobileBottomNavAtomItem(
              icon: Icons.home_outlined, label: 'Home'),
          MiniloMobileBottomNavAtomItem(
              icon: Icons.search_outlined, label: 'Search'),
          MiniloMobileBottomNavAtomItem(
              icon: Icons.person_outline, label: 'Profile'),
          MiniloMobileBottomNavAtomItem(icon: Icons.more_horiz, label: 'More'),
        ],
        currentIndex: 1,
      ),
    ),
    WidgetCatalogEntry(
      route: '/tabs/top-tabs',
      group: 'Tabs',
      title: 'Top Tabs',
      previewSize: const Size(273, 48),
      builder: (_) => MiniloTopTabs(
        tabs: const ['Active Tab', 'In-Active Tab'],
        currentIndex: 0,
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/tabs/tab-pills',
      group: 'Tabs',
      title: 'Tab Pills',
      previewSize: const Size(279, 40),
      builder: (_) => MiniloTabPills(
        tabs: const ['Active tab', 'In-Active Tab'],
        currentIndex: 0,
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/tabs/primary-tabs',
      group: 'Tabs',
      title: 'Primary Tabs',
      previewSize: const Size(328, 48),
      builder: (_) => MiniloPrimaryTabs(
        tabs: const ['Primary Tab 1', 'Primary Tab 2'],
        currentIndex: 0,
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/tabs/secondary-tabs',
      group: 'Tabs',
      title: 'Secondary Tabs',
      previewSize: const Size(328, 48),
      builder: (_) => MiniloSecondaryTabs(
        tabs: const ['Secondary Tab 1', 'Secondary Tab 2'],
        currentIndex: 0,
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/tabs/side-tabs',
      group: 'Tabs',
      title: 'Side Tabs',
      previewSize: const Size(205, 280),
      builder: (_) => MiniloSideTabs(
        items: const [
          MiniloSideTabItemData(
            label: 'Heading 1',
            state: MiniloSideTabState.active,
            iconState: MiniloSideTabIconState.checked,
          ),
          MiniloSideTabItemData(
            label: 'Heading 2',
            state: MiniloSideTabState.inactive,
            iconState: MiniloSideTabIconState.checked,
          ),
          MiniloSideTabItemData(
            label: 'Heading 3',
            state: MiniloSideTabState.active,
            iconState: MiniloSideTabIconState.unchecked,
          ),
          MiniloSideTabItemData(
            label: 'Heading 4',
            state: MiniloSideTabState.inactive,
            iconState: MiniloSideTabIconState.unchecked,
          ),
        ],
        onTap: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/stepper/desktop',
      group: 'Stepper',
      title: 'Stepper Desktop',
      previewSize: const Size(720, 96),
      builder: (_) => SizedBox(
        width: 720,
        child: MiniloStepperDesktop(
          currentStep: 1,
          steps: const [
            MiniloStepData(title: 'Account', complete: true),
            MiniloStepData(title: 'Document', complete: false),
            MiniloStepData(title: 'Review', complete: false),
          ],
          onStepTap: (_) {},
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/stepper/mobile',
      group: 'Stepper',
      title: 'Stepper Mobile',
      previewSize: const Size(375, 44),
      builder: (_) => const SizedBox(
        width: 375,
        child: MiniloStepperMobile(
          currentStep: 2,
          totalSteps: 5,
          title: 'Mobile Stepper For App',
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/search/mobile-default',
      group: 'Search',
      title: 'Search Mobile (Default)',
      previewSize: const Size(343, 48),
      builder: (_) =>
          const MiniloSearchMobile(state: MiniloSearchMobileState.defaultState),
    ),
    WidgetCatalogEntry(
      route: '/search/mobile-typing',
      group: 'Search',
      title: 'Search Mobile (Typing)',
      previewSize: const Size(343, 48),
      builder: (_) =>
          const MiniloSearchMobile(state: MiniloSearchMobileState.typing),
    ),
    WidgetCatalogEntry(
      route: '/search/mobile-typed',
      group: 'Search',
      title: 'Search Mobile (Typed)',
      previewSize: const Size(343, 592),
      builder: (_) => const MiniloSearchMobile(
        state: MiniloSearchMobileState.typed,
        recentSearches: ['News', 'New York', 'Sensex', 'Claim'],
        popularSearches: ['Payslips', 'Account Settings', 'Privacy Policy'],
      ),
    ),
    WidgetCatalogEntry(
      route: '/pagination/web',
      group: 'Pagination',
      title: 'Web Pagination',
      previewSize: const Size(1097, 42),
      builder: (_) => MiniloWebPagination(
        page: 2,
        totalPages: 5,
        pageSize: 6,
        totalItems: 30,
        onPageChanged: (_) {},
        onPageSizeChanged: (_) {},
      ),
    ),
    WidgetCatalogEntry(
      route: '/layout/section-header',
      group: 'Layout',
      title: 'Section Header',
      previewSize: const Size(375, 156),
      builder: (_) => const SizedBox(
        width: 375,
        child: MiniloSectionHeader(
          eyebrow: 'Minilo Flutter',
          title: 'Section Header',
          description: 'Use this header to introduce blocks.',
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/layout/page-footer',
      group: 'Layout',
      title: 'Page Footer',
      previewSize: const Size(375, 80),
      builder: (_) => const SizedBox(
        width: 375,
        child: MiniloPageFooter(
          title: 'Page Footer',
          subtitle: 'Footer helper text',
        ),
      ),
    ),
    WidgetCatalogEntry(
      route: '/layout/sidebar-tips-card',
      group: 'Layout',
      title: 'Sidebar Tips Card',
      previewSize: const Size(250, 232),
      builder: (_) => const MiniloSidebarTipsCard(
        title: 'Tips',
        items: [
          'Lorem ipsum dummy text to be replaced here.',
          'Another helper tip for users in this section.',
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/charts/pie-chart-card',
      group: 'Charts',
      title: 'Pie Chart Card',
      previewSize: const Size(343, 220),
      builder: (_) => const MiniloPieChartCard(
        title: 'Pie Chart',
        slices: [
          MiniloPieSlice(
            label: 'Gross Pay',
            value: 83000,
            formattedValue: '₹ 83,000',
            color: Color(0xFF003078),
          ),
          MiniloPieSlice(
            label: 'Total Deduction',
            value: 12800,
            formattedValue: '₹ 12,800',
            color: Color(0xFFDF5743),
          ),
          MiniloPieSlice(
            label: 'Net Pay',
            value: 70200,
            formattedValue: '₹ 70,200',
            color: Color(0xFF629D83),
          ),
        ],
      ),
    ),
    WidgetCatalogEntry(
      route: '/containers/container-card',
      group: 'Containers',
      title: 'Container Card',
      previewSize: const Size(343, 260),
      builder: (_) => const MiniloContainerCard(),
    ),
    WidgetCatalogEntry(
      route: '/containers/sample-container-one',
      group: 'Containers',
      title: 'Sample Container One',
      previewSize: const Size(343, 320),
      builder: (_) => const MiniloSampleContainerOne(isLoading: false),
    ),
    WidgetCatalogEntry(
      route: '/more/accordion',
      group: 'More',
      title: 'Accordion',
      previewSize: const Size(343, 72),
      builder: (_) => const SizedBox(
        width: 343,
        child: MiniloAccordion(
          title: 'Accordion Title',
          child: Text('Accordion content'),
        ),
      ),
    ),
  ];
}
1
likes
140
points
15
downloads

Documentation

API reference

Publisher

verified publisherminilo.io

Weekly Downloads

Official Minilo Design System component library for Flutter.

Topics

#design-system #flutter #widget #ui

License

MIT (license)

Dependencies

flutter

More

Packages that depend on minilo_design_system