Skip to content

Sidebar

Terminal window
npx bambiui add sidebar

Import the token file once from your global stylesheet:

@import "./styles/bambi.css";

Then import the component:

import {
Sidebar, SidebarHeader, SidebarContent, SidebarFooter,
SidebarGroup, SidebarGroupLabel, SidebarMenu,
SidebarMenuItem, SidebarMenuButton, SidebarMenuLink, SidebarRail,
} from './components/ui/sidebar';

Use props/config-driven Sidebar props for common navigation. Use compound markup for advanced layouts, custom structure, or full control. Both styles render the same sidebar sections, groups, menus, items, and rail.

<Sidebar
header={<span>My App</span>}
footer={<button type="button">Log out</button>}
groups={[
{
label: "Navigation",
items: [
{ label: "Home", href: "/", active: true },
{ label: "Settings", href: "/settings" },
],
},
]}
/>
<Sidebar side="left" collapsible="offcanvas">
<SidebarHeader>
<span>My App</span>
</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Navigation</SidebarGroupLabel>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuLink href="/" active>Home</SidebarMenuLink>
</SidebarMenuItem>
<SidebarMenuItem>
<SidebarMenuLink href="/settings">Settings</SidebarMenuLink>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarMenuButton>Log out</SidebarMenuButton>
</SidebarFooter>
<SidebarRail />
</Sidebar>
ModeBehavior
offcanvasSlides off-screen; shows a backdrop overlay on mobile
iconShrinks to icon-only width; text labels are hidden
noneAlways visible; no collapse behavior
const [open, setOpen] = useState(true);
<Sidebar open={open} onOpenChange={setOpen}>
...
</Sidebar>

Sub-part classes usable in any framework:

ClassElement
bambi-sidebarRoot nav element
bambi-sidebar-headerTop header section
bambi-sidebar-contentScrollable main area
bambi-sidebar-footerBottom footer section
bambi-sidebar-groupNav item group
bambi-sidebar-group-labelGroup heading text
bambi-sidebar-menu<ul> nav list
bambi-sidebar-menu-item<li> item wrapper
bambi-sidebar-menu-buttonButton/link nav item
bambi-sidebar-overlayOffcanvas backdrop
bambi-sidebar-railCollapse toggle strip
PropTypeDefaultDescription
side'left' | 'right''left'Which side the sidebar is on
collapsible'icon' | 'offcanvas' | 'none''offcanvas'Collapse behavior
defaultOpenbooleantrueInitial open state (uncontrolled)
openbooleanControlled open state
onOpenChange(open: boolean) => voidReact/Svelte/Vue open state callback
headerReact node / Svelte snippet / Vue or Astro slotConvenience header section
footerReact node / Svelte snippet / Vue or Astro slotConvenience footer section
groupsArray<{ label?: string; items: SidebarItem[] }>Config-driven grouped navigation
itemsSidebarItem[]Config-driven ungrouped navigation

SidebarItem supports label, href, active, disabled, optional React icon, and button-style onClick where the framework supports function props.

SidebarHeader, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarMenu, SidebarMenuItem all forward HTMLAttributes of their respective elements.

SidebarMenuButton adds active?: boolean and disabled?: boolean.

SidebarMenuLink (renders <a>) adds active?: boolean.

SidebarRail renders the collapse toggle button; reads open state from context.

  • The root element is <nav aria-label="Sidebar navigation"> — provides a landmark for screen readers.
  • The rail toggle button has aria-label, aria-expanded, and is a real <button> element.
  • Active items should use aria-current="page" (handled automatically by SidebarMenuLink/SidebarMenuButton when active is set).
  • Disabled items use data-disabled and aria-disabled; pointer-events: none prevents interaction.
  • Tab order flows naturally through the sidebar; focus is not trapped in persistent mode.
  • In offcanvas mode, the overlay dismisses the sidebar on click and when it is open the sidebar receives focus.