Skip to content

Sidebar

Wrap the whole layout in SidebarProvider to share open state.

useSidebar() exposes the sidebar state and controls to any component inside the provider.

On mobile the sidebar renders as a slide-in drawer, closed by default. It has no built-in open control; place a SidebarTrigger in AppHeader to open it. See App Header for usage details.

Include SidebarActionButton only when the layout calls for a primary action directly in the sidebar (e.g. “New note”, “Create order”).

// Icon logo
<SidebarBrand logo={<FieldIcon />} name="AgVend" />
// Image logo
<SidebarBrand logo={<img src="/logo.png" alt="AgVend" />} name="AgVend" />

When the sidebar is collapsed, SidebarMenuButton can show a flyout menu instead of a plain tooltip.

Pass isActive only to the leaf item the user is currently on. Parent section buttons (those with an expanded prop) never receive the active background; their open state already provides context. In collapsed mode the parent button acts as a leaf and does receive the highlight when a child route is active.

For full app-shell nesting, see Page structure. This example focuses on sidebar navigation pieces.

Code
<SidebarProvider defaultOpen>
<Sidebar>
<SidebarBrand logo={<FieldIcon />} name="AgVend" />
<SidebarContent>
<SidebarActionButton icon={<PencilIcon size={16} />} tooltip="New note">
New note
</SidebarActionButton>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
asChild
isActive
icon={<LayoutDashboardIcon size={16} />}
tooltip="Dashboard"
>
<a href="#dashboard">Dashboard</a>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarContent>
</Sidebar>
</SidebarProvider>
const [sidebarOpen, setSidebarOpen] = React.useState(true);
<SidebarProvider open={sidebarOpen} onOpenChange={setSidebarOpen}>
<AppLayout>{/* sidebar layout */}</AppLayout>
</SidebarProvider>;
<SidebarGroup>
<SidebarGroupLabel>Accounts</SidebarGroupLabel>
<SidebarGroupAction aria-label="Add account">
<PlusIcon />
</SidebarGroupAction>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton
asChild
icon={<UsersIcon size={16} />}
tooltip="Accounts"
>
<a href="#accounts">Accounts</a>
</SidebarMenuButton>
<SidebarMenuBadge>12</SidebarMenuBadge>
<SidebarMenuAction showOnHover aria-label="Account actions">
<MoreHorizontalIcon />
</SidebarMenuAction>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
<SidebarFooter>
<SidebarSeparator />
<SidebarUser
name="Maria Larsen"
menuContent={
<Button variant="ghost" className="tw:w-full tw:justify-start">
Sign out
</Button>
}
/>
</SidebarFooter>
function AccountsSidebarItem() {
const [accountsOpen, setAccountsOpen] = React.useState(true);
return (
<SidebarMenuItem>
<SidebarMenuButton
icon={<UsersIcon size={16} />}
tooltip="Accounts"
expanded={accountsOpen}
onClick={() => setAccountsOpen((open) => !open)}
flyout={[
{ label: "Accounts", isActive: true, render: <a href="#accounts" /> },
{ label: "Leads", render: <a href="#leads" /> },
]}
>
Accounts
</SidebarMenuButton>
{accountsOpen && (
<SidebarMenuSub>
<SidebarMenuSubItem>
<SidebarMenuSubIndicator />
<SidebarMenuSubButton asChild isActive>
<a href="#accounts">Accounts</a>
</SidebarMenuSubButton>
</SidebarMenuSubItem>
</SidebarMenuSub>
)}
</SidebarMenuItem>
);
}

No documented props

NameType/Description
classNamestring | undefined
iconReactNode
onClickMouseEventHandler<Element> | undefined
tooltipstring | undefined
Tooltip text shown when the sidebar is collapsed.
NameType/Description
logoReactNode
Icon or image element that fills the entire 32×32 logo box. Required — in collapsed mode the logo is the only tap target to expand the sidebar.
nameReactNode
Company / app name shown next to the logo in expanded state.

Scrollable navigation region inside Sidebar.

No documented props

Bottom sidebar region for account or secondary controls.

No documented props

Groups related sidebar navigation items under an optional label/action row.

No documented props

Icon action positioned in a SidebarGroup label row.

No documented props

No documented props

Label for a SidebarGroup; hides automatically in collapsed desktop state.

No documented props

No documented props

No documented props

Icon action positioned on a SidebarMenuItem.

NameType/Description
showOnHover = falseboolean | undefined

Count or status badge positioned on a SidebarMenuItem.

No documented props

NameType/Description
asChild = falseboolean | undefined
classNamestring | undefined
expandedboolean | undefined
When provided, renders a chevron indicator on the right. Manage state externally via `onClick`.
flyoutSidebarMenuButtonFlyoutItem[] | undefined
Sub-items shown in a hover flyout when the sidebar is collapsed. Ignored in expanded mode.
iconReactNode
isActive = falseboolean | undefined
onClickMouseEventHandler<Element> | undefined
tooltipstring | undefined

No documented props

No documented props

NameType/Description
asChild = falseboolean | undefined
classNamestring | undefined
isActive = falseboolean | undefined
onClickMouseEventHandler<Element> | undefined

No documented props

No documented props

NameType/Description
defaultOpen = trueboolean | undefined
Initial desktop expanded state for uncontrolled sidebars.
onOpenChange((open: boolean) => void) | undefined
Controlled desktop state change handler.
openboolean | undefined
Controlled desktop expanded state.

No documented props

NameType/Description
icon = "<PanelLeftIcon size={16} />"ReactNode

Footer account control that collapses to initials and can open menu content.

NameType/Description
menuContentReactNode
namestring | undefined
Full name used to render the user row and auto-generate 2-letter initials.