Sidebar
The persistent navigation panel, collapsible to icons
Last action: none.
Usage
import {
Sidebar,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupContent,
SidebarGroupLabel,
SidebarHeader,
SidebarInset,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem,
SidebarProvider,
SidebarRail,
SidebarTrigger,
SidebarUserMenu,
} from "@gpuixui/components";
<SidebarProvider collapsible="icon">
<Sidebar>
<SidebarHeader>…</SidebarHeader>
<SidebarContent>
<SidebarGroup>
<SidebarGroupLabel>Platform</SidebarGroupLabel>
<SidebarGroupContent>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton label="Playground" tooltip="Playground" isActive>
<Icon name="terminal" size="sm" color={theme.colors.accentForeground} />
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
</SidebarGroupContent>
</SidebarGroup>
</SidebarContent>
<SidebarFooter>
<SidebarUserMenu user={{ name: "Benji", email: "benji@example.com" }} />
</SidebarFooter>
<SidebarRail />
</Sidebar>
<SidebarInset>
<SidebarTrigger />
</SidebarInset>
</SidebarProvider>;Composition
SidebarProvider
├── Sidebar
│ ├── SidebarHeader
│ │ └── SidebarMenu
│ │ └── SidebarMenuItem
│ │ ├── SidebarMenuButton
│ │ ├── SidebarMenuAction
│ │ └── SidebarMenuBadge
│ ├── SidebarContent
│ │ └── SidebarGroup
│ │ ├── SidebarGroupLabel
│ │ ├── SidebarGroupAction
│ │ └── SidebarGroupContent
│ │ └── SidebarMenu
│ │ └── SidebarMenuItem
│ │ ├── SidebarMenuButton
│ │ └── SidebarMenuSub
│ │ └── SidebarMenuSubItem
│ │ └── SidebarMenuSubButton
│ ├── SidebarFooter
│ │ └── SidebarUserMenu
│ └── SidebarRail
└── SidebarInsetSidebar renders its children once. On a window narrower than 768px that tree
is the modal sheet; the parts are the same, so a panel does not need a second
layout for mobile.
Behaviour
- Collapsing is
collapsible:"offcanvas"parks the panel outside the window edge,"icon"shrinks it to a 48px rail (64px for the floating and inset variants, which keep theirp-2gutter), and"none"leaves it fixed. The gap in the flow pays the same width, so the content beside it moves by exactly the panel it loses. - The keyboard is ⌘/Ctrl + B.
SIDEBAR_KEYBOARD_SHORTCUTis exported, andtoggleSidebar()is onuseSidebar(). On a narrow window the shortcut opens and closes the sheet. - The open state persists through
SidebarPreference: the default jar uses shadcn'ssidebar_statekey and seven-day lifetime, in process memory. Passpreferenceto keep it across launches. - Icon mode clips the label and publishes the row's
tooltip; only one tip can be open, and the active row keeps its accent.badge,actionand sub-menus hide with the labels, as shadcn's selectors do. - The mobile sheet is a
role="dialog"with a scrim: pressing the scrim dismisses it, Tab wraps inside it, Escape closes it, and focus returns to the trigger. The desktop state is untouched. - The rail toggles on a press and on an 8px drag toward its edge. It stays at the window edge while an offcanvas panel is parked, so the panel can be reopened.
API
| Part | Renders | Props |
|---|---|---|
SidebarProvider | a full-size row and the state | defaultOpen?, open?, onOpenChange?, preference?, side?, variant?, collapsible?, width?, iconWidth?, mobileWidth?, className?, style?, children |
Sidebar | the panel, or the sheet below 768px | side?, variant?, collapsible?, className?, style?, children |
SidebarTrigger | the toggle action | size? |
SidebarRail | the edge strip | className?, style? |
SidebarInset | role="main" content | className?, style?, children |
SidebarHeader | the heading block | className?, children |
SidebarContent | the scrolling middle | className?, style?, children |
SidebarFooter | the footer block | className?, children |
SidebarSeparator | a hairline | className?, style? |
SidebarGroup | a labelled group | className?, children |
SidebarGroupLabel | the group heading (text) | children?, className? |
SidebarGroupAction | an icon-only group action | label, children?, className? |
SidebarGroupContent | the rows under a heading | className?, children |
SidebarMenu | role="list" | className?, children |
SidebarMenuItem | role="listitem" | className?, children |
SidebarMenuButton | a row action | label?, isActive?, variant?, size?, tooltip?, disabled?, children?, trailing?, className?, onClick? |
SidebarMenuAction | a row's trailing action | label, showOnHover?, children?, className? |
SidebarMenuBadge | a row's count | children?, className? |
SidebarMenuSkeleton | a loading row | showIcon?, className? |
SidebarMenuSub | a submenu list | className?, children |
SidebarMenuSubItem | one submenu row | className?, children |
SidebarMenuSubButton | a submenu action | label?, isActive?, size?, disabled?, children?, className?, onClick? |
SidebarInput | a plain field at the panel height | value?, placeholder?, readOnly?, disabled?, className?, style?, testId?, onChange? |
useSidebar | the context | returns state, open, setOpen, openMobile, setOpenMobile, isMobile, toggleSidebar, side, variant, collapsible, tooltip, showTooltip, hideTooltip |
SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON, SIDEBAR_WIDTH_MOBILE, SIDEBAR_BREAKPOINT
and SIDEBAR_KEYBOARD_SHORTCUT are exported from the component module.
Widths and the shortcut
width (default 256, shadcn's 16rem), iconWidth (48, 3rem) and mobileWidth
(288, 18rem) are shadcn's CSS variables as numbers a caller can override. A
non-finite, zero or negative value reads as the default.
The provider hears Cmd/Ctrl+B through the keys that bubble inside its subtree.
GPUix delivers window keys only to the application's render handler, so an app
that wants the shortcut to work with focus outside the sidebar forwards its root
onKeyDown through isSidebarShortcut(event) — the same rule the provider runs.
Edit this page on GitHubpackages/components/docs/sidebar.mdx