Grouped sidebar#
Authored pages chunked into labeled sections — the Settings window. The pages work exactly like a single-tier app; section labels and dividers add visual structure when the destinations fall into categories.
How it works#
add_header(text) adds a quiet, non-interactive section label; add_separator()
adds a divider. The pages added after a header read as belonging to it — the
label’s color and the extra top margin carry the grouping, so the items stay
flush (no indentation).
shell.add_header("Account")
with shell.add_page("profile", text="Profile", icon="person"):
...
shell.add_header("Notifications")
with shell.add_page("email", text="Email", icon="envelope"):
...
Group consistently — put everything under headers, rather than sprinkling loose top-level items among sections. A pinned footer item is the conventional exception.
Example#
1"""Grouped sidebar — pages chunked into labeled sections (a Settings window).
2
3``add_header`` adds a quiet section label and ``add_separator`` a divider; the
4pages between read as a group. Settings screens are the canonical case — related
5panes gathered under Account, Notifications, Advanced. Group *consistently*:
6everything under a header, not loose items sprinkled among sections.
7"""
8import bootstack as bs
9
10with bs.AppShell(title="Settings", size=(860, 580)) as shell:
11 shell.commandbar.add_label("Settings", font="heading-md")
12 shell.commandbar.add_spacer()
13 shell.commandbar.add_button(icon="circle-half", on_click=bs.toggle_theme)
14
15 shell.add_header("Account")
16 with shell.add_page("profile", text="Profile", icon="person"):
17 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
18 bs.Label("Profile", font="heading-lg")
19 bs.Label("Your name, avatar, and bio.")
20 with shell.add_page("security", text="Security", icon="shield-lock"):
21 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
22 bs.Label("Security", font="heading-lg")
23 bs.Label("Password and two-factor authentication.")
24
25 shell.add_header("Notifications")
26 with shell.add_page("email", text="Email", icon="envelope"):
27 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
28 bs.Label("Email notifications", font="heading-lg")
29 with shell.add_page("push", text="Push", icon="bell"):
30 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
31 bs.Label("Push notifications", font="heading-lg")
32
33 shell.add_header("Advanced")
34 with shell.add_page("developer", text="Developer", icon="terminal"):
35 with bs.VStack(fill="both", expand=True, anchor_items="w", gap=8, padding=20):
36 bs.Label("Developer options", font="heading-lg")
37
38 shell.navigate("profile")
39
40shell.run()
When to use#
Use a grouped sidebar when authored pages fall into a few clear categories. If
you find yourself wanting a section that collapses to hide its items, that is a
content concern rather than navigation — compose an
Accordion inside a
custom sidebar. If a “section” is really a long list of
records, use Master–detail (list).