Bridge UI

Sidebar

Persistent app-shell rail with collapse, inset, and a mobile drawer.

Introduction

Sidebar is a persistent app-shell rail. Mount SidebarProvider around Sidebar and SidebarInset as siblings. Put SidebarList or Accordion in the rail. Below the md breakpoint the panel opens as a Drawer.

Sidebar vs Drawer

Prefer Sidebar for app chrome that stays on screen. Prefer Drawer for temporary side panels, filters, and settings that overlay the page.

Mount SidebarProvider around the shell before using SidebarTrigger or useSidebar. BridgeUIProvider still holds theme, tokens, and defaultProps. It does not own instance open state.

Playgrounds sit in a bounded frame so the fixed rail stays in the preview. In an app, mount SidebarProvider at the shell root — it defaults to min-h-svh.

Use the framework selector in the site header to switch between React and Vue.

Import

import {
  Sidebar,
  SidebarInset,
  SidebarList,
  SidebarListItem,
  SidebarProvider,
  SidebarTrigger,
  useSidebar,
} from "@bridge-ui/vue/Components/Sidebar";
import {
  Sidebar,
  SidebarInset,
  SidebarList,
  SidebarListItem,
  SidebarProvider,
  SidebarTrigger,
  useSidebar,
} from "@bridge-ui/react/Components/Sidebar";

Basic usage

Compose the shell: provider, rail, inset, and trigger. SidebarList / SidebarListItem bind nav chrome to the nearest rail.

Put brand and account rows in the header and footer slots. SidebarList collapses those rows to the start avatar. The end chevron hides while collapsed. Give nav items a start icon so they stay visible on the icon rail. Header and footer lists use classes.root "p-0" because those slots are already padded.

Icon collapse

Set collapsible="icon" and use SidebarList / SidebarListItem. Collapsed items keep string primary as an aria-label and show it in a Tooltip on the whole item. Nested SidebarList and ListSection labels are hidden. The mobile drawer keeps labels.

Controlled

Control desktop expanded state on SidebarProvider. There is no cookie or localStorage — persist open in the app if you need it. There is no default keyboard shortcut; call toggleSidebar from useSidebar.

Right side

Set side to right to dock the rail to the opposite edge. Collapsed item tooltips open on the side opposite the rail.

Inset variant

variant="inset" pads and rounds the main column. The default sidebar variant is a flush rail.

Collapsible groups

Use Accordion with variant="plain" for nested nav groups. Put SidebarList in each panel. Plain panels hide while the icon rail is collapsed.

Accordion, Avatar, Button, Drawer, List, Tooltip

Accessibility

  • The desktop panel is an aside with aria-label (default "Sidebar").
  • An offcanvas collapsed panel is inert (out of the tab order). Icon collapse stays focusable.
  • Mobile uses Drawer (dialog, overlay, Escape).
  • SidebarTrigger sets aria-expanded and aria-controls. The default accessible name is Toggle sidebar.
  • SidebarListItem copies string primary to aria-label when the icon rail is collapsed.

Anatomy

div <!-- SidebarProvider -->
  div <!-- Sidebar root: in-flow gap + fixed aside -->
    aside
      header slot
      content <!-- SidebarList / Accordion -->
      footer slot
  main <!-- SidebarInset -->
    SidebarTrigger
    children

Below md, the aside stays mounted and is hidden with CSS. Open state uses a portaled Drawer instead of swapping the rail on first paint.

API

SidebarProvider

Prop Type Default Description
@open-change (open: boolean) => void Emitted when desktop open should change.
classes SidebarProviderClasses Classes for root.
customProps SidebarProviderCustomProps Extra props for the layout wrapper.
defaultOpen boolean true Uncontrolled initial desktop expanded state.
v-model boolean Controlled desktop expanded state.
Prop Type Default Description
children ReactNode Sidebar, SidebarInset, and other shell.
classes SidebarProviderClasses Classes for root.
customProps SidebarProviderCustomProps Extra props for the layout wrapper.
defaultOpen boolean true Uncontrolled initial desktop expanded state.
onOpenChange (open: boolean) => void Called when desktop open should change.
open boolean Controlled desktop expanded state.
Slot Description
default Rail content (SidebarList / Accordion).
footer Sticky footer.
header Sticky header.
Prop Type Default Description
children ReactNode Rail content (SidebarList / Accordion).
slots SidebarSlots header, footer.
Prop Type Default Description
ariaLabel string "Sidebar" Accessible name for the aside and the mobile drawer.
classes SidebarClasses Part classes (root, header, content, footer, gap, panel).
collapsible "icon" | "none" | "offcanvas" "offcanvas" How the desktop rail hides.
customProps SidebarCustomProps Extra props for internal parts.
side "left" | "right" "left" Edge the rail docks to.
variant "inset" | "sidebar" "sidebar" Flush rail or padded main column.

SidebarInset

Prop Type Default Description
classes SidebarInsetClasses Classes for root.
customProps SidebarInsetCustomProps Extra props for the inset root.

SidebarTrigger

Renders a Button. Forwards native button attributes. Default accessible name is Toggle sidebar. Pass children to replace the default icon.

SidebarList

Same as List, plus:

Prop Type Default Description
iconOnly boolean Collapse items to leading icons. Defaults to the collapsed icon rail. Nested lists and ListSection labels are hidden.

Applies stacked nav chrome (gap, compact rows, nested guide). Override with iconOnly.

SidebarListItem

Same as ListItem, plus:

Prop Type Default Description
tooltip string Tooltip label while the icon rail is collapsed. When omitted, string primary is used. No effect on the mobile drawer or an expanded rail.
tooltipPlacement PositionPlacement opposite the rail Placement of the collapsed-rail tooltip.

Applies compact nav chrome. Tooltips only show while the icon rail is collapsed.

useSidebar

Must be called under SidebarProvider. Vue returns a computed context object (sidebar.value.open, …).

Field Type Description
collapsible "icon" | "none" | "offcanvas" Mode from the nearest Sidebar.
isMobile boolean Viewport is below md.
open boolean Desktop expanded state.
openMobile boolean Mobile drawer visibility.
setOpen (open: boolean) => void Sets desktop open.
setOpenMobile (open: boolean) => void Sets mobile drawer visibility.
side "left" | "right" Dock edge.
state "collapsed" | "expanded" Desktop visual state.
toggleSidebar () => void Toggles desktop open or mobile openMobile.
variant "inset" | "sidebar" Visual variant.