Sidebar
A responsive sidebar navigation component with collapsible groups, rail mode, and mobile sheet support.
Usage
Complex
A full-featured sidebar with compact spacing, teamspaces, agents, favorites, recents, and utility footer.
Compact With User Menu
Compact sidebar with a user dropdown menu at the footer.
Agent Hub
Agent-focused sidebar combining compact spacing, workspaces, recent chats, and a user dropdown.
Agent Workspace
Workspace sidebar with agent tasks grouped by repository, inspired by AI coding tools.
Inset Variant
The inset variant uses a transparent sidebar background with a card-like content area.
With Groups
Organize menu items into labeled groups separated by dividers.
Collapsible Groups
Use expandable/collapsible groups for documentation-style navigation with guide lines.
Collapsible
Enable collapsible="icon" to allow the sidebar to collapse into an icon-only rail. Press Cmd+B to toggle.
Reduced Motion
Pass reduceMotion to Sidebar.Provider to disable nested Sidebar.Menu expand/collapse animation across the sidebar.
Floating Variant
The floating variant renders the sidebar with rounded corners and a shadow.
With Avatar
Display a user avatar in the sidebar header with a collapsible layout.
Right Side
Position the sidebar on the right by setting side="right" on the provider.
Icon Only
A permanently collapsed icon-only sidebar with tooltips on each item.
Client-Side Routing
Sidebar.MenuItem supports navigation via the href prop. Because RAC TreeItem elements cannot be rendered as <a> tags due to HTML spec limitations, navigation is handled programmatically through a navigate callback on Sidebar.Provider.
Pass your router's navigation function to the navigate prop, and add href to any Sidebar.MenuItem that should navigate:
Next.js (App Router)
"use client";
import { useRouter } from "next/navigation";
function AppSidebar() {
const router = useRouter();
return (
<Sidebar.Provider navigate={router.push}>
<Sidebar>
<Sidebar.Content>
<Sidebar.Menu>
<Sidebar.MenuItem href="/dashboard">
<Sidebar.MenuIcon><HomeIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>Dashboard</Sidebar.MenuLabel>
</Sidebar.MenuItem>
<Sidebar.MenuItem href="/settings">
<Sidebar.MenuIcon><SettingsIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>Settings</Sidebar.MenuLabel>
</Sidebar.MenuItem>
</Sidebar.Menu>
</Sidebar.Content>
</Sidebar>
<Sidebar.Main>{/* ... */}</Sidebar.Main>
</Sidebar.Provider>
);
}React Router
import { useNavigate } from "react-router";
function AppSidebar() {
const navigate = useNavigate();
return (
<Sidebar.Provider navigate={navigate}>
<Sidebar>
{/* ... */}
<Sidebar.MenuItem href="/dashboard">
<Sidebar.MenuIcon><HomeIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>Dashboard</Sidebar.MenuLabel>
</Sidebar.MenuItem>
{/* ... */}
</Sidebar>
<Sidebar.Main>{/* ... */}</Sidebar.Main>
</Sidebar.Provider>
);
}TanStack Router
import { useRouter } from "@tanstack/react-router";
function AppSidebar() {
const router = useRouter();
return (
<Sidebar.Provider navigate={(href) => router.navigate({ to: href })}>
<Sidebar>
{/* ... */}
<Sidebar.MenuItem href="/dashboard">
<Sidebar.MenuIcon><HomeIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>Dashboard</Sidebar.MenuLabel>
</Sidebar.MenuItem>
{/* ... */}
</Sidebar>
<Sidebar.Main>{/* ... */}</Sidebar.Main>
</Sidebar.Provider>
);
}External Links and Force Reload
External URLs (starting with http:// or https://) are automatically opened in a new tab via window.open. For internal links that need a full page reload instead of client-side navigation, use the forceReload prop:
<Sidebar.MenuItem href="https://github.com/heroui-inc/heroui">
<Sidebar.MenuIcon><GithubIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>GitHub</Sidebar.MenuLabel>
</Sidebar.MenuItem>
<Sidebar.MenuItem href="/legacy-page" forceReload>
<Sidebar.MenuIcon><ExternalLinkIcon /></Sidebar.MenuIcon>
<Sidebar.MenuLabel>Legacy Page</Sidebar.MenuLabel>
</Sidebar.MenuItem>If no
navigatefunction is provided,hreffalls back towindow.location.hreffor navigation.
CSS Classes
Base & Variant Classes
.sidebar— The sidebar panel. Flex column withh-svh, transitions on width and box-shadow..sidebar--default— Default variant with an inset box-shadow border separator..sidebar--floating— Rounded with shadow, margin, andbg-surface. Detached from the edge..sidebar--inset— Transparent background with no border or shadow..sidebar--left— Left-side positioning (default)..sidebar--right— Right-side positioning withorder: 1.
Layout Classes
.sidebar__provider— Layout wrapper for sidebar + main content.flex min-h-svh w-full..sidebar__offcanvas-wrapper— Collapsing spacer for offcanvas mode. Width transitions to0when collapsed..sidebar__main— Main content area.flex-1withmin-h-svh..sidebar__mobile— Mobile Sheet wrapper. Full-height flex column.
Section Classes
.sidebar__header— Top section with flex column layout and padding..sidebar__content— Scrollable middle section wrappingScrollShadow.flex-1withoverflow-y: auto..sidebar__footer— Bottom section with flex column layout and padding..sidebar__group— Flex column group with top margin between siblings..sidebar__group-label— Muted group heading label. Hidden when sidebar is collapsed.
Menu Classes
.sidebar__menu— Tree-based menu container. Flex column withgap-0.5..sidebar__menu-section— Section grouping within a menu with top margin..sidebar__menu-header— Section heading label. Muted, uppercase, hidden when collapsed..sidebar__menu-item— Individual menu row. Relative positioned with transition on box-shadow..sidebar__menu-item-content— Inner content wrapper with flex layout,min-h-9, androunded-2xl. Indented via--sidebar-menu-item-offset..sidebar__menu-trigger— Expand/collapse toggle button (size-5). Hidden when item has no children..sidebar__menu-indicator— Chevron icon that rotates 90° when expanded..sidebar__menu-icon— Icon slot (size-5) with muted color..sidebar__menu-label— Label text with truncation andtext-sm..sidebar__menu-label-text— Inner text span withtext-ellipsisandwhitespace-nowrap..sidebar__menu-chip— Trailing badge/counter with muted color andtabular-nums..sidebar__menu-actions— Action buttons container. Hidden by default, shown on hover or when current..sidebar__menu-action— Individual action button with hover/pressed background transitions.
Utility Classes
.sidebar__separator— Horizontal divider with vertical margin..sidebar__rail— Thin edge strip for toggling. Absolute positioned with directional resize cursor.
Interactive States
- Collapsed (icon):
[data-state="collapsed"]— width transitions to--sidebar-width-collapsed. Labels, chips, and actions are hidden. Items center their icon. - Collapsed (offcanvas):
[data-state="collapsed"][data-collapsible="offcanvas"]— sidebar slides off-screen viatranslate: -100% 0(or100%for right side). - Expanded:
[data-state="expanded"]— full--sidebar-widthwith all content visible. - Item hover:
.sidebar__menu-item:hover .sidebar__menu-item-content— appliesbg-default. - Item current:
[data-current="true"]on.sidebar__menu-item— appliesbg-defaultto content andfont-mediumto label. - Item focus visible:
[data-focus-visible="true"]on.sidebar__menu-item— applies focus ring to content. - Item disabled:
[aria-disabled="true"]on.sidebar__menu-item— applies disabled styles. - Guide lines always:
[data-guide-lines="always"]— repeating vertical guide lines via::beforepseudo-element. - Guide lines hover:
[data-guide-lines="hover"]— guide lines fade in on menu hover. - Rail hover:
.sidebar__rail:hover— changes the sidebar edge outline color. - Mobile:
@media (max-width: 768px)— desktop sidebar is hidden,Sidebar.Mobilerenders a Sheet. - Reduced motion:
@media (prefers-reduced-motion: reduce)— disables all transitions.
CSS Variables
--sidebar-width— Expanded sidebar width (default:240px).--sidebar-width-collapsed— Collapsed sidebar width for icon mode (default:48px).--sidebar-duration— Transition duration (default:200ms).--sidebar-ease— Transition easing (default:ease).--sidebar-edge-outline— Border color for the default variant edge.--sidebar-menu-indent— Indentation width per nesting level (default:calc(var(--spacing) * 4)).--sidebar-menu-guide-color— Guide line color (default:color-mix(in srgb, currentColor 10%, transparent)).--sidebar-menu-row-gap— Vertical gap between menu rows (default:calc(var(--spacing) * 0.5)).--sidebar-menu-item-offset— Per-item left offset based onaria-level(set automatically).
API Reference
Sidebar.Provider
Layout wrapper that provides sidebar context to all children. Wraps both the sidebar and main content.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | — | Controlled open/expanded state. |
defaultOpen | boolean | true | Initial open state (uncontrolled). |
onOpenChange | (open: boolean) => void | — | Callback when open state changes. |
side | "left" | "right" | "left" | Which side the sidebar is on. |
variant | "sidebar" | "floating" | "inset" | "sidebar" | Visual style variant. |
collapsible | "icon" | "offcanvas" | "none" | "icon" | Collapse behavior. "icon" collapses to icon-only, "offcanvas" slides off-screen, "none" disables collapse. |
navigate | (href: string) => void | — | Programmatic navigation function for client-side routing (e.g. router.push). Called when a Sidebar.MenuItem with href is pressed. |
reduceMotion | boolean | false | Disables nested Sidebar.Menu expand/collapse animations for all menus inside the provider. The user's reduced-motion preference is still respected. |
Sidebar
The sidebar panel element. Renders an <aside> tag.
Sidebar.Header
Top section of the sidebar. Renders a <div> with flex column layout.
Sidebar.Content
Scrollable middle section. Wraps HeroUI ScrollShadow with hideScrollBar.
Also supports all HeroUI ScrollShadow props.
Sidebar.Footer
Bottom section of the sidebar. Renders a <div> with flex column layout.
Sidebar.Group
Groups related menu items or content with optional spacing between groups. Renders a <div>.
| Prop | Type | Default | Description |
|---|---|---|---|
closeMobileOnAction | boolean | true | Whether pressing a menu item in this group automatically closes the mobile sidebar sheet. Inherited by all Sidebar.Menu and Sidebar.MenuItem descendants. |
Sidebar.GroupLabel
Label for a sidebar group. Hidden when the sidebar is collapsed. Renders a <div>.
Sidebar.Menu
Tree-based menu container backed by RAC Tree. Supports keyboard navigation and guide lines.
| Prop | Type | Default | Description |
|---|---|---|---|
closeMobileOnAction | boolean | inherited from Sidebar.Group or true | Whether pressing a menu item automatically closes the mobile sidebar sheet. Overrides the group-level setting. |
reduceMotion | boolean | inherited from Sidebar.Provider | Disables submenu expand/collapse animations for this menu only. The user's reduced-motion preference is still respected. |
showGuideLines | boolean | "hover" | true | Whether to show submenu guide lines. true = always, false = never, "hover" = on menu hover only. |
Also supports all RAC Tree props (selection-related props are disallowed).
Sidebar.MenuSection
Section grouping within a menu.
Also supports all RAC TreeSection props.
Sidebar.MenuHeader
Section heading label within a menu. Hidden when collapsed.
Also supports all RAC TreeHeader props.
Sidebar.MenuItem
An individual menu item that can contain icons, labels, actions, chips, and nested submenus.
| Prop | Type | Default | Description |
|---|---|---|---|
closeMobileOnAction | boolean | inherited | Override the inherited closeMobileOnAction for this specific item. Set to false to keep the mobile sidebar open when this item is pressed. |
forceReload | boolean | false | Force a full page reload instead of client-side navigation. Uses window.location.href instead of the Provider's navigate function. |
href | string | — | URL to navigate to. Uses the Provider's navigate function for client-side routing, or window.location.href as a fallback. External URLs (http://https://) open in a new tab. |
isCurrent | boolean | false | Marks the item as the current page (aria-current="page"). |
tooltip | ReactNode | Item label text | Tooltip content shown when the sidebar is collapsed to icon-only. |
tooltipProps | SidebarMenuItemTooltipProps | — | Props for an always-visible tooltip wrapping the item content. |
Also supports all RAC TreeItem props.
Sidebar.MenuItemContent
Wrapper for the content rendered inside a menu item. Children are rendered directly.
Sidebar.MenuIcon
Icon slot inside a menu item. Renders a <span> with size-5.
Sidebar.MenuLabel
Label text inside a menu item. Automatically separates trailing Sidebar.MenuTrigger elements. Renders a <span>.
Sidebar.MenuChip
Trailing badge/counter inside a menu item. Renders a <span> with muted color and tabular-nums.
Sidebar.MenuActions
Container for action buttons inside a menu item. Hidden by default, shown on hover or when current.
Sidebar.MenuAction
An individual action button inside the actions container.
Also supports all RAC Button props.
Sidebar.MenuTrigger
Expand/collapse toggle for items with children. Hidden when item has no child items.
Also supports all RAC Button props.
Sidebar.MenuIndicator
Chevron icon that rotates when an item is expanded. Accepts custom children to replace the default icon.
Sidebar.Submenu
Wrapper for nested child items. Children are rendered as tree sub-items.
Sidebar.Separator
Horizontal divider.
Also supports all HeroUI Separator props.
Sidebar.Trigger
Toggle button for opening/closing the sidebar. Renders a HeroUI Button with variant="ghost" and size="sm".
Also supports all HeroUI Button props.
Sidebar.Rail
Thin edge strip for toggling the sidebar by clicking. Shows directional resize cursor.
Sidebar.Main
Main content area next to the sidebar. Renders a <main> tag with flex-1.
Sidebar.Mobile
Mobile-only Sheet wrapper. Renders nothing on desktop. On mobile, wraps children in a Sheet that slides from the sidebar's side.
| Prop | Type | Default | Description |
|---|---|---|---|
backdrop | "blur" | "opaque" | "transparent" | "blur" | Backdrop style for the mobile sheet. |
Sidebar.Tooltip
Tooltip wrapper that only shows when the sidebar is collapsed. When expanded, renders children directly.
| Prop | Type | Default | Description |
|---|---|---|---|
content | ReactNode | — | Tooltip content shown when sidebar is collapsed. |
placement | "top" | "bottom" | "left" | "right" | "right" | Tooltip placement. |
delay | number | — | Delay in ms before showing the tooltip. |
closeDelay | number | — | Delay in ms before hiding the tooltip. |
useSidebar
A hook for programmatic sidebar control.
const { isOpen, setOpen, isMobile, isMobileOpen, setMobileOpen, toggleSidebar, side, variant, collapsible } = useSidebar();| Property | Type | Description |
|---|---|---|
isOpen | boolean | Current desktop open/expanded state. |
setOpen | (open: boolean) => void | Set the desktop open state. |
isMobile | boolean | Whether the viewport is at mobile width (≤768px). |
isMobileOpen | boolean | Current mobile sheet open state (independent from desktop). |
setMobileOpen | (open: boolean) => void | Set the mobile sheet open state. |
toggleSidebar | () => void | Toggle the sidebar open/closed (desktop or mobile depending on viewport). |
side | "left" | "right" | Which side the sidebar is on. |
variant | "sidebar" | "floating" | "inset" | Current visual variant. |
collapsible | "icon" | "offcanvas" | "none" | Current collapse behavior. |