Composable primary navigation with provider state, collapse modes, and a List Item menu hierarchy.
Also known as: app sidebar, navigation sidebar, vertical nav, primary nav, side navigation, labeled nav, app shell nav
Install with the CLI, or copy the component source into your project.
Add sidebar (npm)
1npx --yes -p @default-file/ui df-ui add sidebar
Docked primary navigation with List Item rows, icon collapse, and separators between groups.
thumb and edge scrollbar styles. visibility hover shows the bar only while the panel is hovered.
thumb
edge
Icon collapse shrinks the panel to icon width. SidebarMenuItem tooltip shows labels while collapsed.
Rounded floating panel with border and elevation.
Inset panel with margin, radius, and elevation on SidebarInset.
Slides the panel off the edge. In frame layout the seam cannot reopen while collapsed, so keep a SidebarTrigger in SidebarInset.
Override the SidebarInput fill with background.
Hover a List Item to open Option List beside the panel. Use width fill and OptionListSubmenu for nested levels.
Composable primary navigation. SidebarProvider owns open state, height, and collapse defaults. Compose header, scrollable content, and footer with List Item rows.
Layout wrapper and context host. Wrap Sidebar and SidebarInset.
| Prop | Type | Default | Notes |
|---|---|---|---|
| defaultOpen | boolean | true | Initial expanded state when uncontrolled. |
| open | boolean | - | Controlled expanded state on desktop. |
| onOpenChange | (open: boolean) => void | - | Called when desktop open state changes. |
| layout | "app" | "frame" | "app" | app uses fixed viewport chrome. frame positions inside a sized host. |
| fillHeight | boolean | true | Stretch to the viewport (app) or host (frame). When false, height hugs content. Ignored when height is set. |
| height | string | - | Fixed height. Sets --df-sidebar-height and wins over fillHeight. |
| variant | "docked" | "floating" | "inset" | "docked" | Default appearance for nested Sidebar. |
| collapsible | "offcanvas" | "icon" | "none" | "icon" | Default collapse mode for nested Sidebar. |
| edgeCollapse | boolean | true | Default for nested Sidebar. Double-click the content-facing seam to toggle on desktop. Ignored when collapsible is none or on mobile. Unavailable in frame layout while offcanvas is collapsed. |
| edgeBorder | boolean | true | Default for nested Sidebar. Shows a seam hover accent when edgeCollapse is enabled. |
| side | "left" | "right" | "left" | Default edge for nested Sidebar. |
| label | string | "Sidebar" | Accessible name for toggles and the mobile panel. |
| keyboardShortcut | boolean | true | When true, mod+b toggles the sidebar. |
| width | string | - | Overrides --df-sidebar-width. |
| iconWidth | string | - | Overrides --df-sidebar-width-icon. Omit to track paddingInline. |
| mobileWidth | string | - | Overrides --df-sidebar-width-mobile. |
| padding | string | - | Sets --df-sidebar-padding-block and --df-sidebar-padding-inline to the same length. |
| paddingBlock | string | - | Overrides --df-sidebar-padding-block on the panel. |
| paddingInline | string | - | Overrides --df-sidebar-padding-inline. Also feeds default --df-sidebar-width-icon unless iconWidth is set. |
| radius | string | - | Panel corner radius. Sets --df-sidebar-radius and --df-sidebar-radius-floating. |
| sectionRadius | string | - | Default radius for header, footer section, footer, and groups. |
| itemRadius | string | - | Radius for menu buttons and group labels. |
| gap | string | - | Gap inside header and footer stacks. |
| groupGap | string | - | Default gap inside SidebarGroup. Override per group with SidebarGroup gap. |
| groupPadding | string | - | Default padding on all SidebarGroup axes. |
| groupPaddingBlock | string | - | Default SidebarGroup block padding. |
| groupPaddingInline | string | - | Default SidebarGroup inline padding. |
| groupPaddingBlockStart | string | - | Default SidebarGroup padding-block-start. |
| groupPaddingBlockEnd | string | - | Default SidebarGroup padding-block-end. |
| groupPaddingInlineStart | string | - | Default SidebarGroup padding-inline-start. |
| groupPaddingInlineEnd | string | - | Default SidebarGroup padding-inline-end. |
| menuItemNestPaddingBottom | string | false | - | Default bottom space for a last-in-menu item that owns SidebarMenuSub. Pass false for 0. Forced to 0 while icon-collapsed. Override per row with nestPaddingBottom. |
| children | ReactNode | - | Typically Sidebar and SidebarInset. |
Panel shell. Compose SidebarHeader, SidebarContent, optional SidebarFooterSection, and optional SidebarFooter. On mobile, children render in an overlay panel.
| Prop | Type | Default | Notes |
|---|---|---|---|
| side | "left" | "right" | - | Overrides the provider side. |
| variant | "docked" | "floating" | "inset" | - | docked is flush with an inner-edge border. floating insets the rail over the workspace fill. inset elevates SidebarInset. |
| collapsible | "offcanvas" | "icon" | "none" | - | offcanvas slides away. icon collapses to icon width. none stays expanded. |
| edgeCollapse | boolean | - | Overrides the provider. Enables the seam double-click toggle on desktop. Unavailable in frame layout while offcanvas is collapsed; use SidebarTrigger to reopen. |
| edgeBorder | boolean | - | Overrides the provider. Shows the seam hover accent when edgeCollapse is enabled. |
| children | ReactNode | - | Header, Content, Footer, Group, and Menu parts. |
Main workspace region beside the sidebar peer.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Page or tool content. |
Ghost icon button that calls toggleSidebar.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Optional custom icon. Defaults to PanelLeft. |
Sticky top region. For icon collapse, keep one leading control beside optional data-df="sidebar-brand-copy".
| Prop | Type | Default | Notes |
|---|---|---|---|
| radius | string | - | Corner radius for this section. Defaults to --df-sidebar-section-radius. |
| children | ReactNode | - | Brand row, SidebarTrigger, and SidebarInput. |
Scrollable middle region with a kit ScrollArea. Place SidebarGroup parts here. Do not nest another ScrollArea.
| Prop | Type | Default | Notes |
|---|---|---|---|
| separators | boolean | false | When true, insert a SidebarSeparator between each child. Fragments and arrays flatten first. Skips neighbors that are already separators. Does not affect footer parts. |
| scrollbar | "thumb" | "edge" | "thumb" | thumb uses --df-sidebar-scrollbar-track-inset. edge uses --df-sidebar-scrollbar-edge-inset (default 0, flush). |
| thumbShape | "rounded" | "flat" | "rounded" | ScrollArea thumb corner shape. |
| orientation | "vertical" | "horizontal" | "both" | "vertical" | ScrollArea axes. |
| side | "left" | "right" | "top" | "bottom" | - | ScrollArea scrollbar edge. Defaults to the content-facing side of the sidebar. |
| visibility | "hover" | "always" | "always" | ScrollArea thumb visibility. |
| space | "auto" | "none" | "none" | ScrollArea track inset. Defaults to none. Forced to none while icon-collapsed. |
| width | number | - | ScrollArea scrollbar thickness in pixels. |
| viewportClassName | string | - | Classes on the ScrollArea viewport. |
| children | ReactNode | - | Typically SidebarGroup parts. |
Sticky utility stack after SidebarContent. Pins alone or above SidebarFooter. Use for Settings, Help, and similar rows.
| Prop | Type | Default | Notes |
|---|---|---|---|
| radius | string | - | Corner radius for this section. Defaults to --df-sidebar-section-radius. |
| paddingBlockEnd | string | false | token (--df-sidebar-footer-section-padding-block-end) | Bottom padding after utility rows. Defaults to --df-sidebar-section-gap. Pass false for 0. After FooterSection, panel section-gap to the next Footer or separator collapses so this padding owns that air. |
| children | ReactNode | - | Menu rows, SidebarSeparator, or custom chrome. |
Sticky bottom region after content and FooterSection. Prefer SidebarSeparator, then SidebarProfileMenu for the account switcher.
| Prop | Type | Default | Notes |
|---|---|---|---|
| radius | string | - | Corner radius for this section. Defaults to --df-sidebar-section-radius. |
| children | ReactNode | - | SidebarSeparator, SidebarProfileMenu, or custom chrome. |
SearchInput for the header. Default pill variant. Hidden in icon collapse.
| Prop | Type | Default | Notes |
|---|---|---|---|
| size | "sm" | "md" | "lg" | "md" | SearchInput size. |
| variant | "default" | "pill" | "pill" | SearchInput shape. |
| clearable | boolean | false | Show the clear control when the field has a value. |
| background | string | - | Field fill. Prefer tokens such as var(--muted). Overrides the pill resting and filled recipes. |
Separator with sidebar chrome. Prefer SidebarContent separators for rules between groups.
| Prop | Type | Default | Notes |
|---|---|---|---|
| orientation | "horizontal" | "vertical" | "horizontal" | Direction of the rule. |
| decorative | boolean | true | When true, treated as presentational for assistive tech. |
| color | string | - | Rule color. Sets --df-sidebar-separator. |
| className | string | - | Additional classes on the Separator root. |
| style | CSSProperties | - | Inline styles on the Separator root. |
Nav section with optional label and content. Set collapsible to expand and collapse the body.
| Prop | Type | Default | Notes |
|---|---|---|---|
| collapsible | boolean | false | Show a chevron on SidebarGroupLabel that toggles SidebarGroupContent. |
| open | boolean | - | Controlled open state when collapsible. |
| defaultOpen | boolean | true | Uncontrolled initial open state when collapsible. |
| onOpenChange | (open: boolean) => void | - | Called when open changes while collapsible. |
| radius | string | - | Corner radius for this section. Defaults to --df-sidebar-section-radius. |
| gap | string | - | Gap between the label, optional separators, and content. |
| padding | string | - | Sets all four group padding axes to the same length. |
| paddingBlock | string | - | Sets group padding-block-start and padding-block-end. |
| paddingInline | string | - | Sets group padding-inline-start and padding-inline-end. |
| paddingBlockStart | string | - | Sets --df-sidebar-group-padding-block-start. |
| paddingBlockEnd | string | - | Sets --df-sidebar-group-padding-block-end. |
| paddingInlineStart | string | - | Sets --df-sidebar-group-padding-inline-start. |
| paddingInlineEnd | string | - | Sets --df-sidebar-group-padding-inline-end. |
| children | ReactNode | - | SidebarGroupLabel, SidebarGroupContent, and optional SidebarSeparator. |
Section title from Label with as="div". Collapsible groups append a chevron in the trailing slot.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Group title text. |
| leading | ReactNode | - | Slot before the title. Prefer FeaturedIcon plain at size sm with glyphShadow off. |
| trailing | ReactNode | - | Optional trailing meta before the collapsible chevron. |
| color | string | - | Title color. Defaults to --df-sidebar-group-label-fg. |
| fontFamily | string | - | Title font family. Sets --df-label-font. |
| fontSize | string | - | Title font size. Sets --df-label-size. |
| fontWeight | string | - | Title font weight. Sets --df-label-weight. |
| asChild | boolean | false | Merge props onto a single child. Skips the automatic collapsible chevron. |
| className | string | - | Additional classes on the root. |
| style | CSSProperties | - | Inline styles on the root. |
Trailing icon button for SidebarGroupLabel. Collapsible groups render a chevron automatically.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Usually a single icon. |
| asChild | boolean | false | Merge props onto a single child element. |
| className | string | - | Additional classes on the control. |
Group body. Collapsible groups animate open and closed and set inert while closed.
| Prop | Type | Default | Notes |
|---|---|---|---|
| forceMount | boolean | true | Keep content mounted while closed so height can animate. |
| children | ReactNode | - | Usually a SidebarMenu. |
| className | string | - | Additional classes on the content body. |
Semantic ul for navigation and utility rows. Use SidebarProfileMenu for the account switcher in SidebarFooter.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | SidebarMenuItem rows. |
Semantic ul for the account switcher in SidebarFooter. Place SidebarMenuItem rows with a stacked List Item trigger.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | SidebarMenuItem rows for the profile trigger. |
List row wrapper. Place a List Item as the interactive child. Optional SidebarMenuSub, SidebarMenuBadge, and SidebarMenuAction are siblings.
| Prop | Type | Default | Notes |
|---|---|---|---|
| tooltip | ReactNode | - | Shown when the sidebar is icon-collapsed on desktop. |
| nestPaddingBottom | string | false | - | Bottom space when this item owns a direct SidebarMenuSub and is last in its menu. Pass false to disable. Forced to 0 while icon-collapsed. |
| children | ReactNode | - | List Item row, plus optional SidebarMenuSub, SidebarMenuBadge, or SidebarMenuAction. |
| className | string | - | Additional classes on the li. |
Deprecated compatibility shim over List Item. Prefer List Item inside SidebarMenuItem.
| Prop | Type | Default | Notes |
|---|---|---|---|
| asChild | boolean | false | Forwards to List Item asChild. |
| isActive | boolean | false | Maps to List Item selected. |
| size | "sm" | "md" | "lg" | "md" | Maps to List Item size. |
| variant | "default" | "outline" | "default" | outline adds a hairline ring via a shim class. |
| tooltip | ReactNode | - | Legacy collapsed tooltip. Prefer tooltip on SidebarMenuItem. |
| children | ReactNode | - | Leading icon plus label. |
Absolute action control on a menu item.
| Prop | Type | Default | Notes |
|---|---|---|---|
| showOnHover | boolean | false | Hide until the item is hovered or focused. |
| asChild | boolean | false | Merge props onto a single child element. |
Trailing count or status badge on a menu item.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Badge content. |
Nested menu list with a leading guide border. Hidden in icon mode.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | SidebarMenuSubItem rows with List Item children. |
Nested list row. Place a List Item as the interactive child.
| Prop | Type | Default | Notes |
|---|---|---|---|
| children | ReactNode | - | Usually a List Item. |
| className | string | - | Additional classes on the li. |
Deprecated compatibility shim over List Item for nested rows. Prefer List Item inside SidebarMenuSubItem.
| Prop | Type | Default | Notes |
|---|---|---|---|
| asChild | boolean | false | Forwards to List Item asChild. |
| isActive | boolean | false | Maps to List Item selected. |
| size | "sm" | "md" | "md" | "sm" maps to List Item xs. "md" maps to List Item md. |
| children | ReactNode | - | Nested row label or asChild link. |
Loading placeholder row for menu lists.
| Prop | Type | Default | Notes |
|---|---|---|---|
| showIcon | boolean | false | Show a leading icon skeleton beside the text bar. |
| className | string | - | Additional classes on the skeleton row. |
Context hook. Throws when used outside SidebarProvider.
| Prop | Type | Default | Notes |
|---|---|---|---|
| state | "expanded" | "collapsed" | - | Desktop expand state. |
| open | boolean | - | Desktop expanded when true. |
| setOpen | (open: boolean | ((value: boolean) => boolean)) => void | - | Set desktop open state. |
| openMobile | boolean | - | Mobile overlay open state. |
| setOpenMobile | (open: boolean) => void | - | Set mobile overlay open state. |
| isMobile | boolean | - | True when the mobile breakpoint is active. |
| toggleSidebar | () => void | - | Toggle desktop open or mobile overlay. |
| side | "left" | "right" | - | Provider default edge. |
| variant | "docked" | "floating" | "inset" | - | Provider default appearance. |
| collapsible | "offcanvas" | "icon" | "none" | - | Provider default collapse mode. |
| edgeCollapse | boolean | - | Provider default for the seam toggle. |
| edgeBorder | boolean | - | Provider default for the seam hover accent. |
| layout | "app" | "frame" | - | Provider layout mode. |
| fillHeight | boolean | - | Provider fillHeight prop value. |
| heightMode | "fill" | "fixed" | "auto" | - | Resolved height mode from height and fillHeight. |
| label | string | - | Accessible name for toggles and the mobile panel. |
| hostRef | RefObject<HTMLDivElement | null> | - | Ref to the SidebarProvider host element. |
Theme defaults live on :root. Override these globally or on a local host.
| Token | Type | Default | Notes |
|---|---|---|---|
| --df-sidebar-width | CSS length | calc(64 * var(--spacing-unit)) | Expanded desktop width. |
| --df-sidebar-width-icon | CSS length | calc(var(--df-sidebar-menu-button-height-md) + (2 * var(--df-sidebar-padding-inline))) | Icon-collapse width. Defaults to one md menu button plus inline padding. |
| --df-sidebar-width-mobile | CSS length | calc(72 * var(--spacing-unit)) | Mobile overlay width. |
| --df-sidebar-height | CSS length | auto | Fixed shell height when SidebarProvider height is set. |
| --df-sidebar-padding-block | CSS length | calc(4 * var(--spacing-unit)) | Block padding on the sidebar panel. |
| --df-sidebar-padding-inline | CSS length | calc(4 * var(--spacing-unit)) | Inline padding on header, footer section, footer, and the content viewport. Feeds default --df-sidebar-width-icon. |
| --df-sidebar-padding | CSS padding | var(--df-sidebar-padding-block) var(--df-sidebar-padding-inline) | Shorthand for panel block padding and section inline padding. |
| --df-sidebar-item-padding-inline | CSS length | calc(2 * var(--spacing-unit)) | Inline padding inside menu buttons, group labels, and matching header rows. |
| --df-sidebar-gap | CSS length | calc(3 * var(--spacing-unit)) | Gap inside header and footer stacks. |
| --df-sidebar-section-gap | CSS length | calc(2 * var(--spacing-unit)) | Gap between panel sections and between sections in SidebarContent. |
| --df-sidebar-footer-section-padding-block-end | CSS length | var(--df-sidebar-section-gap) | Default bottom padding on SidebarFooterSection. Override with paddingBlockEnd. |
| --df-sidebar-scrollbar-track-inset | CSS length | calc(1 * var(--spacing-unit)) | Content-facing inset for the thumb scrollbar in SidebarContent. |
| --df-sidebar-scrollbar-edge-inset | CSS length | 0px | Content-facing inset for the edge scrollbar in SidebarContent. Default 0 is flush. |
| --df-sidebar-group-gap | CSS length | 0px | Gap inside SidebarGroup. |
| --df-sidebar-group-padding-block-start | CSS length | 0px | SidebarGroup padding-block-start. |
| --df-sidebar-group-padding-block-end | CSS length | 0px | SidebarGroup padding-block-end. |
| --df-sidebar-group-padding-inline-start | CSS length | 0px | SidebarGroup padding-inline-start. |
| --df-sidebar-group-padding-inline-end | CSS length | 0px | SidebarGroup padding-inline-end. |
| --df-sidebar-menu-gap | CSS length | calc(1 * var(--spacing-unit)) | Gap between menu rows inside SidebarMenu. |
| --df-sidebar-menu-item-nest-padding-bottom | CSS length | calc(2 * var(--spacing-unit)) | Bottom padding on a last-in-menu SidebarMenuItem that owns a direct SidebarMenuSub. |
| --df-sidebar-floating-inset | CSS length | calc(2 * var(--spacing-unit)) | Outer inset for floating and inset variants. |
| --df-sidebar-bg | CSS color | var(--sidebar) | Panel background. |
| --df-input-bg | CSS color | var(--df-search-input-bg) | SidebarInput field fill. Override with SidebarInput background. |
| --df-search-input-bg | CSS color | color-mix(in oklch, var(--muted) 28%, var(--background)) | SidebarInput pill resting fill. |
| --df-search-input-bg-filled | CSS color | color-mix(in oklch, var(--muted) 48%, var(--background)) | SidebarInput pill filled fill. |
| --df-sidebar-fg | CSS color | var(--sidebar-foreground) | Panel foreground. |
| --df-sidebar-border | CSS color | var(--sidebar-border) | Panel border and edge hover accent. |
| --df-sidebar-motion-duration | CSS time | var(--df-duration-panel-soft) | Duration for expand and collapse shell travel. |
| --df-sidebar-motion-ease | CSS easing | var(--df-ease-emphasized) | Easing for expand and collapse shell travel. |
| --df-sidebar-motion-fade-duration | CSS time | var(--df-duration-theme) | Duration for content fades during icon collapse. |
| --df-sidebar-motion-fade-ease | CSS easing | var(--df-ease-decelerate) | Easing for content fades during icon collapse. |
| --df-sidebar-motion-fade-delay-expand | CSS time | var(--df-duration-base) | Delay before content fades in when expanding from icon mode. |
| --df-sidebar-edge-hit-width | CSS length | calc(2 * var(--spacing-unit)) | Desktop hit width for the content-facing seam toggle. |
| --df-sidebar-edge-cursor-emphasize-left | CSS cursor | url(...) 16 16, w-resize | Seam cursor when the available action is toward the left. |
| --df-sidebar-edge-cursor-emphasize-right | CSS cursor | url(...) 16 16, e-resize | Seam cursor when the available action is toward the right. |
| --df-sidebar-z-edge | number | 20 | Stacking for the content-facing seam hit target. |
| --df-sidebar-separator | CSS color | var(--df-sidebar-border) | SidebarSeparator rule color. |
| --df-sidebar-accent | CSS color | var(--sidebar-accent) | Hover and active fill. |
| --df-sidebar-menu-button-height-md | CSS length | calc(8 * var(--spacing-unit)) | Default menu row height. |
| --df-sidebar-radius | CSS length | 0 | Docked panel radius. |
| --df-sidebar-radius-floating | CSS length | var(--radius-xl) | Floating and inset panel radius. |
| --df-sidebar-section-radius | CSS length | 0 | Default radius for header, footer section, footer, and groups. |
| --df-sidebar-item-radius | CSS length | var(--radius-md) | Radius for menu buttons and group labels. |
| --df-sidebar-group-label-fg | CSS color | var(--muted-foreground) | Default SidebarGroupLabel title color. |
| --df-demo-stage-height | CSS length | 600px | Shared height for docs workspace stage frames. |
| --df-sidebar-mobile-scrim | CSS color | color-mix(in oklch, var(--foreground) 40%, transparent) | Mobile overlay scrim behind the panel. |