Navigation

Sidebar

A sidebar widget that provides an opinionated layout for navigation on the side of the screen.

A sidebar is typically used with FScaffold. Usage of FScaffold can be found here.

FScaffold(
  sidebar: FSidebar(
    header: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
            child: SvgPicture.network(
              theme.colors.brightness == Brightness.light
                  ? 'https://forui.dev/light_logo.svg'
                  : 'https://forui.dev/dark_logo.svg',
              height: 24,
              colorFilter: ColorFilter.mode(context.theme.colors.foreground, BlendMode.srcIn),
            ),
          ),
          FDivider(style: context.theme.dividerStyles.horizontalStyle.copyWith(padding: EdgeInsets.zero)),
        ],
      ),
    ),
    footer: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: FCard.raw(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
          child: Row(
            spacing: 10,
            children: [
              FAvatar.raw(child: Icon(FIcons.userRound, size: 18, color: context.theme.colors.mutedForeground)),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  spacing: 2,
                  children: [
                    Text(
                      'Dash',
                      style: context.theme.typography.sm.copyWith(
                        fontWeight: FontWeight.bold,
                        color: context.theme.colors.foreground,
                      ),
                      overflow: TextOverflow.ellipsis,
                    ),
                    Text(
                      'dash@forui.dev',
                      style: context.theme.typography.xs.copyWith(color: context.theme.colors.mutedForeground),
                      overflow: TextOverflow.ellipsis,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    ),
    children: [
      FSidebarGroup(
        label: const Text('Overview'),
        children: [
          FSidebarItem(
            icon: const Icon(FIcons.school),
            label: const Text('Getting Started'),
            initiallyExpanded: true,
            onPress: () {},
            children: [
              FSidebarItem(label: const Text('Installation'), selected: true, onPress: () {}),
              FSidebarItem(label: const Text('Themes'), onPress: () {}),
              FSidebarItem(label: const Text('Typography'), onPress: () {}),
            ],
          ),
          FSidebarItem(icon: const Icon(FIcons.code), label: const Text('API Reference'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.box), label: const Text('Pub Dev'), onPress: () {}),
        ],
      ),
      FSidebarGroup(
        action: const Icon(FIcons.plus),
        onActionPress: () {},
        label: const Text('Widgets'),
        children: [
          FSidebarItem(icon: const Icon(FIcons.circleSlash), label: const Text('Divider'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.scaling), label: const Text('Resizable'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.layoutDashboard), label: const Text('Scaffold'), onPress: () {}),
        ],
      ),
    ],
  ),
  child: Padding(
    padding: const EdgeInsets.symmetric(vertical: 14),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      spacing: 12,
      children: [
        FBreadcrumb(
          children: [
            FBreadcrumbItem(onPress: () {}, child: const Text('Forui')),
            FBreadcrumbItem.collapsed(
              menu: [
                FItemGroup(
                  children: [
                    FItem(title: const Text('Documentation'), onPress: () {}),
                    FFItemTile(title: const Text('Themes'), onPress: () {}),
                  ],
                ),
              ],
            ),
            FBreadcrumbItem(onPress: () {}, child: const Text('Overview')),
            const FBreadcrumbItem(current: true, child: Text('Installation')),
          ],
        ),
        Expanded(
          child: Container(
            decoration: BoxDecoration(
              color: context.theme.colors.muted,
              borderRadius: context.theme.style.borderRadius,
            ),
          ),
        ),
        Expanded(
          flex: 3,
          child: Container(
            decoration: BoxDecoration(
              color: context.theme.colors.muted,
              borderRadius: context.theme.style.borderRadius,
            ),
          ),
        ),
      ],
    ),
  ),
);

CLI

To generate and customize this style:

dart run forui style create sidebar

Anatomy

This segment describes the anatomy of the various elements of a sidebar.

FSidebar

The widget that provides an opinionated layout on the side of the screen. The widget has the following sections:

NameParameterPositionOptional
headerheaderstickyYes
contentchild/childrenscrollableNo
footerfooterstickyYes

FSidebarGroup

A widget that is used to group several FSidebarItems.

FSidebarItem

Represents an item on the sidebar. May be nested in FSidebarItem.children to create nested items.

Usage

FSidebar(...)

FSidebar(
  style: (style) => style.copyWith(...),
  header: const Text('Header'),
  footer: const Text('Footer'),
  children: [FSidebarGroup(...)],
);

FSidebar.builder(...)

FSidebar.builder(
  style: (style) => style.copyWith(...),
  header: const Text('Header'),
  footer: const Text('Footer'),
  itemCount: 5,
  itemBuilder: (context, index) => FSidebarGroup(...),
);

FSidebar.raw(...)

FSidebar.raw(
  style: (style) => style.copyWith(...),
  header: const Text('Header'),
  footer: const Text('Footer'),
  child: const SizedBox(),
);

FSidebarGroup(...)

FSidebarGroup(
  style: (style) => style.copyWith(...),
  label: const Text('Group'),
  action: const Icon(FIcons.plus),
  onActionPress: () {},
  children: [FSidebarItem(...)],
);

FSidebarItem(...)

FSidebarItem(
  style: (style) => style.copyWith(...),
  icon: const Icon(FIcons.box),
  label: const Text('Item'),
  selected: false,
  initiallyExpanded: false,
  onPress: () {},
  onLongPress: () {},
  onHoverChange: (hovered) {},
  onStateChange: (delta) {},
  children: [FSidebarItem(...)],
);

Examples

Sheet Sidebar

Suited for devices with limited screen space.

Widget _sidebar(BuildContext context) => DecoratedBox(
  decoration: BoxDecoration(color: context.theme.colors.background),
  child: FSidebar(
    style: (s) => s.copyWith(constraints: s.constraints.copyWith(minWidth: 300, maxWidth: 300)),
    header: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Padding(
            padding: const EdgeInsets.fromLTRB(16, 8, 16, 16),
            child: SvgPicture.network(
              theme.colors.brightness == Brightness.light
                  ? 'https://forui.dev/light_logo.svg'
                  : 'https://forui.dev/dark_logo.svg',
              height: 24,
              colorFilter: ColorFilter.mode(context.theme.colors.foreground, BlendMode.srcIn),
            ),
          ),
          FDivider(style: context.theme.dividerStyles.horizontalStyle.copyWith(padding: EdgeInsets.zero)),
        ],
      ),
    ),
    footer: Padding(
      padding: const EdgeInsets.symmetric(horizontal: 16),
      child: FCard.raw(
        child: Padding(
          padding: const EdgeInsets.symmetric(vertical: 12, horizontal: 16),
          child: Row(
            spacing: 10,
            children: [
              FAvatar.raw(child: Icon(FIcons.userRound, size: 18, color: context.theme.colors.mutedForeground)),
              Expanded(
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  spacing: 2,
                  children: [
                    Text(
                      'Dash',
                      style: context.theme.typography.sm.copyWith(
                        fontWeight: FontWeight.bold,
                        color: context.theme.colors.foreground,
                      ),
                      overflow: TextOverflow.ellipsis,
                    ),
                    Text(
                      'dash@forui.dev',
                      style: context.theme.typography.xs.copyWith(color: context.theme.colors.mutedForeground),
                      overflow: TextOverflow.ellipsis,
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    ),
    children: [
      FSidebarGroup(
        label: const Text('Overview'),
        children: [
          FSidebarItem(
            icon: const Icon(FIcons.school),
            label: const Text('Getting Started'),
            initiallyExpanded: true,
            onPress: () {},
            children: [
              FSidebarItem(label: const Text('Installation'), selected: true, onPress: () {}),
              FSidebarItem(label: const Text('Themes'), onPress: () {}),
              FSidebarItem(label: const Text('Typography'), onPress: () {}),
            ],
          ),
          FSidebarItem(icon: const Icon(FIcons.code), label: const Text('API Reference'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.box), label: const Text('Pub Dev'), onPress: () {}),
        ],
      ),
      FSidebarGroup(
        action: const Icon(FIcons.plus),
        onActionPress: () {},
        label: const Text('Widgets'),
        children: [
          FSidebarItem(icon: const Icon(FIcons.circleSlash), label: const Text('Divider'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.scaling), label: const Text('Resizable'), onPress: () {}),
          FSidebarItem(icon: const Icon(FIcons.layoutDashboard), label: const Text('Scaffold'), onPress: () {}),
        ],
      ),
    ],
  ),
);

@override
Widget build(BuildContext context) => Center(
  child: FButton(
    child: const Text('Open Sidebar'),
    onPress: () => showFSheet(context: context, side: FLayout.ltr, builder: _sidebar),
  ),
);

Custom Width

FSidebar(
  style: (s) => s.copyWith(constraints: s.constraints.copyWith(minWidth: 500, maxWidth: 500)),
  children: [
    FSidebarGroup(
      children: [
        FSidebarItem(
          icon: const Icon(FIcons.layoutDashboard),
          label: const Text('Dashboard'),
          selected: true,
          onPress: () {},
        ),
        FSidebarItem(icon: const Icon(FIcons.chartLine), label: const Text('Analytics'), onPress: () {}),
        FSidebarItem(
          icon: const Icon(FIcons.chartBar),
          label: const Text('Reports'),
          initiallyExpanded: true,
          children: [
            FSidebarItem(label: const Text('Daily'), onPress: () {}),
            FSidebarItem(label: const Text('Weekly'), onPress: () {}),
            FSidebarItem(label: const Text('Monthly'), onPress: () {}),
          ],
        ),
      ],
    ),
  ],
);

Nested FSidebarItem

FSidebar(
style: (s) => s.copyWith(constraints: s.constraints.copyWith(minWidth: 300, maxWidth: 300)),
children: [
  FSidebarGroup(
    children: [
      FSidebarItem(
        icon: const Icon(FIcons.userRound),
        label: const Text('Account'),
        initiallyExpanded: true,
        children: [
          FSidebarItem(
            label: const Text('Profile'),
            children: [
              FSidebarItem(label: const Text('Personal Info'), onPress: () {}),
              FSidebarItem(label: const Text('Preferences'), onPress: () {}),
            ],
          ),
          FSidebarItem(
            label: const Text('Security'),
            initiallyExpanded: true,
            children: [
              FSidebarItem(
                label: const Text('Password'),
                initiallyExpanded: true,
                children: [
                  FSidebarItem(label: const Text('Change Password'), onPress: () {}),
                  FSidebarItem(label: const Text('Password History'), onPress: () {}),
                ],
              ),
              FSidebarItem(label: const Text('Two-Factor Authentication'), onPress: () {}),
              FSidebarItem(label: const Text('Device History'), onPress: () {}),
            ],
          ),
          FSidebarItem(label: const Text('Notifications'), onPress: () {}),
        ],
      ),
      FSidebarItem(icon: const Icon(FIcons.palette), label: const Text('Appearance'), onPress: () {}),
      FSidebarItem(icon: const Icon(FIcons.settings), label: const Text('System'), onPress: () {}),
    ],
  ),
],
);

On this page