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 sidebarAnatomy
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:
| Name | Parameter | Position | Optional |
|---|---|---|---|
| header | header | sticky | Yes |
| content | child/children | scrollable | No |
| footer | footer | sticky | Yes |
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: () {}),
],
),
],
);