Sidebar
A composable, multi-variant application sidebar with collapsible groups, nested menus, icon-only mode, mobile sheet overlay, and keyboard shortcut toggle. Supports default, floating, and inset layouts.
Overview
The Sidebar is a composable, multi-variant application sidebar system. It supports app sidebars with team/user switchers, docs sidebars with collapsible groups, floating and inset layouts, icon-only collapse mode, mobile sheet overlay, and keyboard shortcut toggle (Ctrl+B / ⌘B).
Installation
Install the component via the CLI in one command.
npx @work-rjkashyap/unified-ui add sidebarpnpm dlx @work-rjkashyap/unified-ui add sidebarnpx @work-rjkashyap/unified-ui add sidebarbunx @work-rjkashyap/unified-ui add sidebarIf you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for
details.
Or install the full package
Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.
npm install @work-rjkashyap/unified-uipnpm add @work-rjkashyap/unified-uiyarn add @work-rjkashyap/unified-uibun add @work-rjkashyap/unified-uiAnatomy
import {
SidebarProvider,
Sidebar,
SidebarTrigger,
SidebarHeader,
SidebarContent,
SidebarFooter,
SidebarGroup,
SidebarGroupLabel,
SidebarGroupAction,
SidebarGroupContent,
SidebarMenu,
SidebarMenuItem,
SidebarMenuButton,
SidebarMenuAction,
SidebarMenuBadge,
SidebarMenuSub,
SidebarMenuSubItem,
SidebarMenuSubButton,
SidebarMenuSkeleton,
SidebarSeparator,
SidebarInput,
SidebarRail,
SidebarInset,
} from "@work-rjkashyap/unified-ui";Architecture
The Sidebar is a compound component composed of multiple parts organized in a strict hierarchy:
<SidebarProvider> ← State management (collapse, mobile, variant)
<Sidebar> ← The sidebar container
<SidebarHeader /> ← Sticky top area (logo, team switcher)
<SidebarContent> ← Scrollable middle area
<SidebarGroup> ← Logical section (collapsible or static)
<SidebarGroupLabel /> ← Section heading
<SidebarGroupAction /> ← Action button in group header
<SidebarGroupContent> ← Wrapper for items
<SidebarMenu> ← Nav list (<ul>)
<SidebarMenuItem> ← Nav item (<li>)
<SidebarMenuButton /> ← Clickable nav button/link
<SidebarMenuAction /> ← Trailing action (chevron, more)
<SidebarMenuBadge /> ← Badge/count indicator
<SidebarMenuSub> ← Nested sub-menu
<SidebarMenuSubItem>
<SidebarMenuSubButton />
<SidebarFooter /> ← Sticky bottom area (user, actions)
<SidebarRail /> ← Thin toggle rail at edge
<SidebarInset> ← Main content area (sibling to Sidebar)Sub-component Reference
| Sub-component | Purpose |
|---|---|
SidebarProvider | Context provider — manages open/collapsed state, variant, mobile detect. |
Sidebar | The sidebar container with desktop animation and mobile sheet. |
SidebarTrigger | Button to toggle sidebar open/closed. |
SidebarHeader | Sticky top area (logo, team switcher, branding). |
SidebarContent | Scrollable middle area for groups and items. |
SidebarFooter | Sticky bottom area (user profile, account actions). |
SidebarGroup | Logical section container within sidebar content. |
SidebarGroupLabel | Section heading text (auto-hides in icon-collapse mode). |
SidebarGroupAction | Action button in group header row (+, −, etc.). |
SidebarGroupContent | Wrapper for the items inside a group. |
SidebarMenu | Navigation list (<ul>). |
SidebarMenuItem | Single item wrapper (<li>). |
SidebarMenuButton | Clickable nav button with icon, label, tooltip, sizes, variants. |
SidebarMenuAction | Trailing action button (more options, expand chevron). |
SidebarMenuBadge | Badge/count indicator within a menu item. |
SidebarMenuSkeleton | Loading placeholder for a menu item. |
SidebarMenuSub | Nested sub-menu list with left border indicator. |
SidebarMenuSubItem | Sub-menu item wrapper. |
SidebarMenuSubButton | Clickable sub-navigation link. |
SidebarSeparator | Horizontal divider within the sidebar. |
SidebarInput | Search/filter input styled for the sidebar. |
SidebarRail | Thin vertical bar at sidebar edge for toggle affordance. |
SidebarInset | Main content area that sits beside the sidebar. |
Variants
The sidebar supports three visual variants controlled via the variant prop on SidebarProvider or Sidebar.
Default Variant
The standard bordered sidebar. This is the default.
Floating Variant
A rounded sidebar with margin, shadow, and border — appears as a standalone floating panel.
Inset Variant
The sidebar is inset within a parent container. The main content area gets rounded corners and a subtle shadow.
Collapsible Modes
The sidebar supports three collapsible behaviors controlled via the collapsible prop.
Offcanvas (default)
The sidebar slides completely off-screen when collapsed.
Icon
Collapses to a narrow icon-only width (48px). Labels hide and tooltips appear on hover. This is the mode shown in the second reference image.
None
The sidebar is not collapsible. Good for static documentation sidebars.
Basic Usage
Wrap your layout in SidebarProvider and place Sidebar alongside SidebarInset for main content.
Groups
Use SidebarGroup to organize navigation items into labeled sections.
Static Groups
Collapsible Groups
Wrap the group label and content with the Collapsible component for expand/collapse behavior. This matches the docs sidebar with +/− toggles pattern.
Group with Action Button
Add an action button to a group header using SidebarGroupAction. Useful for "add" buttons.
Menu Items
Basic Menu Button
Active State
Mark the current page with isActive:
Menu Button Sizes
Three sizes are available: sm, default, and lg. Use lg for header/footer team or user switchers.
Outline Variant
With Badge
Show a notification count or indicator next to the item:
With Action Button
Add a trailing action button (e.g., "more options") that appears on hover:
Nested Sub-menus
Show hierarchical navigation with nested sub-menus. The sub-menu renders an indented list with a left border line.
Header with Team Switcher
Use SidebarMenuButton with size="lg" in the header paired with a DropdownMenu for a team/workspace switcher:
Footer with User Menu
Use the same pattern in the footer for a user account dropdown:
Sidebar Input
Add a search/filter input at the top of the sidebar:
Sidebar Separator
Add horizontal dividers between groups:
Sidebar Rail
Add a thin toggle rail at the sidebar edge for a hover-to-toggle affordance:
Sidebar Trigger
Place a toggle button in the main content header to expand/collapse the sidebar:
Loading State
Show skeleton placeholders while navigation data is loading:
Controlled State
Control the sidebar's open/closed state externally:
const [open, setOpen] = useState(true);
<SidebarProvider open={open} onOpenChange={setOpen}>
<Sidebar>{/* ... */}</Sidebar>
<SidebarInset>{/* ... */}</SidebarInset>
</SidebarProvider>;
{
/* External toggle */
}
<Button onClick={() => setOpen((prev) => !prev)}>Toggle Sidebar</Button>;useSidebar Hook
Access sidebar state from any descendant component:
function SidebarBrand() {
const { state, open, toggleSidebar, isMobile } = useSidebar();
return (
<div className="flex items-center gap-2">
<Logo />
{state === "expanded" && (
<span className="font-semibold">Acme Inc</span>
)}
</div>
);
}Hook Return Values
| Property | Type | Description |
|---|---|---|
state | "expanded" | "collapsed" | Current visual state of the sidebar. |
open | boolean | Whether the sidebar is open. |
setOpen | (open: boolean) => void | Set open state. |
openMobile | boolean | Whether the mobile sidebar sheet is open. |
setOpenMobile | (open: boolean) => void | Set mobile sidebar open state. |
isMobile | boolean | Whether the viewport is mobile (< 768px). |
toggleSidebar | () => void | Toggle the sidebar open/closed. |
variant | "default" | "floating" | "inset" | Current visual variant. |
collapsible | "offcanvas" | "icon" | "none" | Current collapsible mode. |
side | "left" | "right" | Which side the sidebar is on. |
Right Side
Place the sidebar on the right side of the layout:
Keyboard Shortcut
The sidebar registers Ctrl+B (or ⌘B on macOS) as a global keyboard shortcut to toggle the sidebar. This works automatically when using SidebarProvider.
Full App Layout Example
A complete sidebar layout with team switcher, navigation groups, sub-menus, and user footer.
Docs Sidebar Layout Example
A static, non-collapsible sidebar suitable for documentation sites:
Props
SidebarProvider
| Prop | Type | Default | Description |
|---|---|---|---|
defaultOpen | boolean | true | Initial open state (uncontrolled). |
open | boolean | — | Controlled open state. |
onOpenChange | (open: boolean) => void | — | Called when open state changes. |
variant | "default" | "floating" | "inset" | "default" | Visual variant of the sidebar. |
collapsible | "offcanvas" | "icon" | "none" | "offcanvas" | How the sidebar collapses. |
side | "left" | "right" | "left" | Which side to place the sidebar. |
className | string | — | Additional CSS classes on the wrapper div. |
children | ReactNode | — | Should contain Sidebar + SidebarInset. |
All standard <div> HTML attributes are also forwarded.
Sidebar
| Prop | Type | Default | Description |
|---|---|---|---|
side | "left" | "right" | Provider value | Overrides the provider's side. |
variant | "default" | "floating" | "inset" | Provider value | Overrides the provider's variant. |
collapsible | "offcanvas" | "icon" | "none" | Provider value | Overrides the provider's collapsible mode. |
className | string | — | Additional CSS classes. |
children | ReactNode | — | Header, content, footer, and rail sub-components. |
All standard <div> HTML attributes are also forwarded.
SidebarTrigger
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Custom icon (defaults to PanelLeft icon). |
All standard <button> HTML attributes are also forwarded.
SidebarHeader / SidebarContent / SidebarFooter
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Section content. |
All standard <div> HTML attributes are also forwarded.
SidebarGroup
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Group label, action, and content. |
SidebarGroupLabel
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as a child element (for collapsible triggers). |
className | string | — | Additional CSS classes. |
children | ReactNode | — | Label content. |
SidebarGroupAction
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Action content (typically an icon). |
All standard <button> HTML attributes are also forwarded.
SidebarGroupContent
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | SidebarMenu content. |
SidebarMenu
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | SidebarMenuItem children. |
SidebarMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Menu button, action, badge, or sub-menu. |
SidebarMenuButton
| Prop | Type | Default | Description |
|---|---|---|---|
isActive | boolean | false | Whether this item is the currently active page. |
size | "sm" | "default" | "lg" | "default" | Size of the button. |
variant | "default" | "outline" | "default" | Visual variant. |
tooltip | string | ReactNode | — | Tooltip shown when collapsed to icon-only mode. |
asChild | boolean | false | Render as a span wrapper (for Radix asChild patterns). |
className | string | — | Additional CSS classes. |
children | ReactNode | — | Button content (icon + label). |
All standard <button> HTML attributes are also forwarded.
SidebarMenuAction
| Prop | Type | Default | Description |
|---|---|---|---|
showOnHover | boolean | false | Only show the action on item hover. |
className | string | — | Additional CSS classes. |
children | ReactNode | — | Action content (typically an icon). |
All standard <button> HTML attributes are also forwarded.
SidebarMenuBadge
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Badge content (text, count, icon). |
SidebarMenuSkeleton
| Prop | Type | Default | Description |
|---|---|---|---|
showIcon | boolean | false | Whether to show the icon placeholder. |
className | string | — | Additional CSS classes. |
SidebarMenuSub
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | SidebarMenuSubItem children. |
SidebarMenuSubItem
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Sub-item content. |
SidebarMenuSubButton
| Prop | Type | Default | Description |
|---|---|---|---|
isActive | boolean | false | Whether this sub-item is the currently active page. |
size | "sm" | "md" | "md" | Size of the sub-button. |
className | string | — | Additional CSS classes. |
All standard <a> HTML attributes are also forwarded.
SidebarSeparator
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
SidebarInput
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
All standard <input> HTML attributes are also forwarded.
SidebarRail
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
SidebarInset
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | — | Additional CSS classes. |
children | ReactNode | — | Main content (header, page, etc.). |
Motion
- Sidebar width — Animated with CSS-based linear easing (
duration: 200ms, ease: [0.25, 0.1, 0.25, 1.0]) when toggling between collapsed and expanded states. - Mobile sheet — Slide-in with spring animation (
stiffness: 300, damping: 30, mass: 0.8) from the sidebar's side. - Mobile overlay — Uses the
overlayBackdropmotion preset for a backdrop blur fade. - Tooltips — CSS-based
animate-in/fade-in/zoom-infor icon-mode tooltips. - All animations respect
prefers-reduced-motionvia Framer Motion'suseReducedMotion().
Accessibility
- The sidebar renders inside a semantic
<div>withdata-ds-component="sidebar"for styling hooks. SidebarTriggerhasaria-label("Expand sidebar" / "Collapse sidebar") andaria-expanded.- Active items use
aria-current="page"for assistive technologies. SidebarMenurenders as<ul>andSidebarMenuItemas<li>for proper list semantics.- When collapsed to icon-only mode,
SidebarMenuButtonshows Radix UI tooltips (accessible by keyboard and screen readers). - The mobile overlay dismisses the sidebar on click.
- Keyboard shortcut
Ctrl+B/⌘Btoggles the sidebar globally. - All interactive elements use the design system focus ring for visible keyboard focus.
- The
SidebarRailhastabIndex={-1}to be click-only (not keyboard-focusable).
Design Tokens
| Token | Usage |
|---|---|
--sidebar | Sidebar background color |
--sidebar-foreground | Sidebar text color |
--sidebar-primary | Primary accent (tooltip background) |
--sidebar-primary-foreground | Primary accent text (tooltip text) |
--sidebar-accent | Active/hover item background |
--sidebar-accent-foreground | Active/hover item text color |
--sidebar-border | Sidebar borders, rail, separators |
--sidebar-ring | Focus ring color |
--duration-fast | Hover/focus transition speed |