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.

1@override
2Widget build(BuildContext context) => FScaffold(
3 sidebar: FSidebar(
4 header: Padding(
5 padding: const .symmetric(horizontal: 16),
6 child: Column(
7 crossAxisAlignment: .start,
8 children: [
9 Padding(
10 padding: const .fromLTRB(16, 8, 16, 16),
11 child: SvgPicture.network(
12 context.theme.colors.brightness == .light
13 ? 'https://forui.dev/light_logo.svg'
14 : 'https://forui.dev/dark_logo.svg',
15 height: 24,
16 colorFilter: ColorFilter.mode(
17 context.theme.colors.foreground,
18 .srcIn,
19 ),
20 ),
21 ),
22 const FDivider(style: .delta(padding: .zero)),
23 ],
24 ),
25 ),
26 footer: Padding(
27 padding: const .symmetric(horizontal: 16),
28 child: FCard.raw(
29 child: Padding(
30 padding: const .symmetric(vertical: 12, horizontal: 16),
31 child: Row(
32 spacing: 10,
33 children: [
34 FAvatar.raw(
35 child: Icon(
36 FIcons.userRound,
37 size: 18,
38 color: context.theme.colors.mutedForeground,
39 ),
40 ),
41 Expanded(
42 child: Column(
43 crossAxisAlignment: .start,
44 spacing: 2,
45 children: [
46 Text(
47 'Dash',
48 style: context.theme.typography.sm.copyWith(
49 fontWeight: .bold,
50 color: context.theme.colors.foreground,
51 ),
52 overflow: .ellipsis,
53 ),
54 Text(
55 'dash@forui.dev',
56 style: context.theme.typography.xs.copyWith(
57 color: context.theme.colors.mutedForeground,
58 ),
59 overflow: .ellipsis,
60 ),
61 ],
62 ),
63 ),
64 ],
65 ),
66 ),
67 ),
68 ),
69 children: [
70 FSidebarGroup(
71 label: const Text('Overview'),
72 children: [
73 FSidebarItem(
74 icon: const Icon(FIcons.school),
75 label: const Text('Getting Started'),
76 initiallyExpanded: true,
77 onPress: () {},
78 children: [
79 FSidebarItem(
80 label: const Text('Installation'),
81 selected: true,
82 onPress: () {},
83 ),
84 FSidebarItem(label: const Text('Themes'), onPress: () {}),
85 FSidebarItem(label: const Text('Typography'), onPress: () {}),
86 ],
87 ),
88 FSidebarItem(
89 icon: const Icon(FIcons.code),
90 label: const Text('API Reference'),
91 onPress: () {},
92 ),
93 FSidebarItem(
94 icon: const Icon(FIcons.box),
95 label: const Text('Pub Dev'),
96 onPress: () {},
97 ),
98 ],
99 ),
100 FSidebarGroup(
101 action: const Icon(FIcons.plus),
102 onActionPress: () {},
103 label: const Text('Widgets'),
104 children: [
105 FSidebarItem(
106 icon: const Icon(FIcons.circleSlash),
107 label: const Text('Divider'),
108 onPress: () {},
109 ),
110 FSidebarItem(
111 icon: const Icon(FIcons.scaling),
112 label: const Text('Resizable'),
113 onPress: () {},
114 ),
115 FSidebarItem(
116 icon: const Icon(FIcons.layoutDashboard),
117 label: const Text('Scaffold'),
118 onPress: () {},
119 ),
120 ],
121 ),
122 ],
123 ),
124 child: Padding(
125 padding: const .symmetric(vertical: 14),
126 child: Column(
127 crossAxisAlignment: .start,
128 spacing: 12,
129 children: [
130 FBreadcrumb(
131 children: [
132 FBreadcrumbItem(onPress: () {}, child: const Text('Forui')),
133 FBreadcrumbItem.collapsed(
134 menu: [
135 FItemGroup(
136 children: [
137 FItem(title: const Text('Documentation'), onPress: () {}),
138 FItem(title: const Text('Themes'), onPress: () {}),
139 ],
140 ),
141 ],
142 ),
143 FBreadcrumbItem(onPress: () {}, child: const Text('Overview')),
144 const FBreadcrumbItem(current: true, child: Text('Installation')),
145 ],
146 ),
147 Expanded(
148 child: Container(
149 decoration: BoxDecoration(
150 color: context.theme.colors.muted,
151 borderRadius: context.theme.style.borderRadius,
152 ),
153 ),
154 ),
155 Expanded(
156 flex: 3,
157 child: Container(
158 decoration: BoxDecoration(
159 color: context.theme.colors.muted,
160 borderRadius: context.theme.style.borderRadius,
161 ),
162 ),
163 ),
164 ],
165 ),
166 ),
167);
168

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(...)

1FSidebar(
2 style: const .delta(headerPadding: .fromLTRB(0, 16, 0, 0)),
3 header: const Text('Header'),
4 children: [
5 FSidebarGroup(
6 label: const Text('Navigation'),
7 children: [
8 FSidebarItem(
9 icon: const Icon(FIcons.house),
10 label: const Text('Home'),
11 onPress: () {},
12 ),
13 FSidebarItem(
14 icon: const Icon(FIcons.settings),
15 label: const Text('Settings'),
16 onPress: () {},
17 ),
18 ],
19 ),
20 ],
21 footer: const Text('Footer'),
22)

FSidebar.builder(...)

1FSidebar.builder(
2 style: const .delta(headerPadding: .fromLTRB(0, 16, 0, 0)),
3 header: const Text('Header'),
4 itemBuilder: (context, index) =>
5 FSidebarItem(label: Text('Item $index'), onPress: () {}),
6 itemCount: 10,
7 footer: const Text('Footer'),
8)

FSidebar.raw(...)

1FSidebar.raw(
2 style: const .delta(headerPadding: .fromLTRB(0, 16, 0, 0)),
3 header: const Text('Header'),
4 child: ListView(
5 children: [FSidebarItem(label: const Text('Custom Item'), onPress: () {})],
6 ),
7 footer: const Text('Footer'),
8)

FSidebarGroup(...)

1FSidebarGroup(
2 style: const .delta(padding: .symmetric(horizontal: 8)),
3 label: const Text('Navigation'),
4 action: const Icon(FIcons.plus),
5 children: [
6 FSidebarItem(label: const Text('Home'), onPress: () {}),
7 FSidebarItem(label: const Text('Settings'), onPress: () {}),
8 ],
9)

FSidebarItem(...)

1FSidebarItem(
2 style: const .delta(padding: .symmetric(horizontal: 8)),
3 selected: false,
4 initiallyExpanded: false,
5 icon: const Icon(FIcons.house),
6 label: const Text('Home'),
7 children: [
8 FSidebarItem(label: const Text('Nested Item 1'), onPress: () {}),
9 FSidebarItem(label: const Text('Nested Item 2'), onPress: () {}),
10 ],
11)

Examples

Sheet Sidebar

Suited for devices with limited screen space.

1@override
2Widget build(BuildContext context) => Center(
3 child: FButton(
4 child: const Text('Open Sidebar'),
5 onPress: () => showFSheet(
6 context: context,
7 side: .ltr,
8 builder: (context) => DecoratedBox(
9 decoration: BoxDecoration(color: context.theme.colors.background),
10 child: FSidebar(
11 style: const .delta(
12 constraints: BoxConstraints(minWidth: 300, maxWidth: 300),
13 ),
14 header: Padding(
15 padding: const .symmetric(horizontal: 16),
16 child: Column(
17 crossAxisAlignment: .start,
18 children: [
19 Padding(
20 padding: const .fromLTRB(16, 8, 16, 16),
21 child: SvgPicture.network(
22 context.theme.colors.brightness == .light
23 ? 'https://forui.dev/light_logo.svg'
24 : 'https://forui.dev/dark_logo.svg',
25 height: 24,
26 colorFilter: ColorFilter.mode(
27 context.theme.colors.foreground,
28 .srcIn,
29 ),
30 ),
31 ),
32 const FDivider(style: .delta(padding: .zero)),
33 ],
34 ),
35 ),
36 footer: Padding(
37 padding: const .symmetric(horizontal: 16),
38 child: FCard.raw(
39 child: Padding(
40 padding: const .symmetric(vertical: 12, horizontal: 16),
41 child: Row(
42 spacing: 10,
43 children: [
44 FAvatar.raw(
45 child: Icon(
46 FIcons.userRound,
47 size: 18,
48 color: context.theme.colors.mutedForeground,
49 ),
50 ),
51 Expanded(
52 child: Column(
53 crossAxisAlignment: .start,
54 spacing: 2,
55 children: [
56 Text(
57 'Dash',
58 style: context.theme.typography.sm.copyWith(
59 fontWeight: .bold,
60 color: context.theme.colors.foreground,
61 ),
62 overflow: .ellipsis,
63 ),
64 Text(
65 'dash@forui.dev',
66 style: context.theme.typography.xs.copyWith(
67 color: context.theme.colors.mutedForeground,
68 ),
69 overflow: .ellipsis,
70 ),
71 ],
72 ),
73 ),
74 ],
75 ),
76 ),
77 ),
78 ),
79 children: [
80 FSidebarGroup(
81 label: const Text('Overview'),
82 children: [
83 FSidebarItem(
84 icon: const Icon(FIcons.school),
85 label: const Text('Getting Started'),
86 initiallyExpanded: true,
87 onPress: () {},
88 children: [
89 FSidebarItem(
90 label: const Text('Installation'),
91 selected: true,
92 onPress: () {},
93 ),
94 FSidebarItem(label: const Text('Themes'), onPress: () {}),
95 FSidebarItem(
96 label: const Text('Typography'),
97 onPress: () {},
98 ),
99 ],
100 ),
101 FSidebarItem(
102 icon: const Icon(FIcons.code),
103 label: const Text('API Reference'),
104 onPress: () {},
105 ),
106 FSidebarItem(
107 icon: const Icon(FIcons.box),
108 label: const Text('Pub Dev'),
109 onPress: () {},
110 ),
111 ],
112 ),
113 FSidebarGroup(
114 action: const Icon(FIcons.plus),
115 onActionPress: () {},
116 label: const Text('Widgets'),
117 children: [
118 FSidebarItem(
119 icon: const Icon(FIcons.circleSlash),
120 label: const Text('Divider'),
121 onPress: () {},
122 ),
123 FSidebarItem(
124 icon: const Icon(FIcons.scaling),
125 label: const Text('Resizable'),
126 onPress: () {},
127 ),
128 FSidebarItem(
129 icon: const Icon(FIcons.layoutDashboard),
130 label: const Text('Scaffold'),
131 onPress: () {},
132 ),
133 ],
134 ),
135 ],
136 ),
137 ),
138 ),
139 ),
140);
141

Custom Width

1@override
2Widget build(BuildContext _) => FSidebar(
3 style: const .delta(
4 constraints: BoxConstraints(minWidth: 500, maxWidth: 500),
5 ),
6 children: [
7 FSidebarGroup(
8 children: [
9 FSidebarItem(
10 icon: const Icon(FIcons.layoutDashboard),
11 label: const Text('Dashboard'),
12 selected: true,
13 onPress: () {},
14 ),
15 FSidebarItem(
16 icon: const Icon(FIcons.chartLine),
17 label: const Text('Analytics'),
18 onPress: () {},
19 ),
20 FSidebarItem(
21 icon: const Icon(FIcons.chartBar),
22 label: const Text('Reports'),
23 initiallyExpanded: true,
24 children: [
25 FSidebarItem(label: const Text('Daily'), onPress: () {}),
26 FSidebarItem(label: const Text('Weekly'), onPress: () {}),
27 FSidebarItem(label: const Text('Monthly'), onPress: () {}),
28 ],
29 ),
30 ],
31 ),
32 ],
33);
34

Nested FSidebarItem

1@override
2Widget build(BuildContext _) => FSidebar(
3 style: const .delta(
4 constraints: BoxConstraints(minWidth: 300, maxWidth: 300),
5 ),
6 children: [
7 FSidebarGroup(
8 children: [
9 FSidebarItem(
10 icon: const Icon(FIcons.userRound),
11 label: const Text('Account'),
12 initiallyExpanded: true,
13 children: [
14 FSidebarItem(
15 label: const Text('Profile'),
16 children: [
17 FSidebarItem(
18 label: const Text('Personal Info'),
19 onPress: () {},
20 ),
21 FSidebarItem(label: const Text('Preferences'), onPress: () {}),
22 ],
23 ),
24 FSidebarItem(
25 label: const Text('Security'),
26 initiallyExpanded: true,
27 children: [
28 FSidebarItem(
29 label: const Text('Password'),
30 initiallyExpanded: true,
31 children: [
32 FSidebarItem(
33 label: const Text('Change Password'),
34 onPress: () {},
35 ),
36 FSidebarItem(
37 label: const Text('Password History'),
38 onPress: () {},
39 ),
40 ],
41 ),
42 FSidebarItem(
43 label: const Text('Two-Factor Authentication'),
44 onPress: () {},
45 ),
46 FSidebarItem(
47 label: const Text('Device History'),
48 onPress: () {},
49 ),
50 ],
51 ),
52 FSidebarItem(label: const Text('Notifications'), onPress: () {}),
53 ],
54 ),
55 FSidebarItem(
56 icon: const Icon(FIcons.palette),
57 label: const Text('Appearance'),
58 onPress: () {},
59 ),
60 FSidebarItem(
61 icon: const Icon(FIcons.settings),
62 label: const Text('System'),
63 onPress: () {},
64 ),
65 ],
66 ),
67 ],
68);
69

On this page