Sidebar
Sidebar components are used to provide a collapsible navigation menu that can be toggled open or closed. They are typically used for site navigation, allowing users to access different sections of the application.
Loading Code Block...Full example
Section titled “Full example”Loading Code Block...Sidebar Stacked
Section titled “Sidebar Stacked”Loading Code Block...Header variants
Section titled “Header variants”The sidebar header is a discriminated union with three explicit configurations. Pass undefined (or omit the prop entirely) to render the sidebar with no header.
headerType | Use case | Notes |
|---|---|---|
'profile' (default) | Avatar + title/description + optional context-switcher dropdown | Sub-modes via variant: 'side-by-side' (default) or 'stacked'. |
'logo' | Single brand image, alignable left/center/right | Useful for marketing-style sidebars. |
| omitted | No header — menu starts at the top | Useful for embedded contexts. |
'profile' is the default for backwards compatibility, so existing consumers don’t need to set headerType explicitly. In Vue, the legacy { profile: { ... } } wrapper is still accepted as a deprecated alias.
Profile header (default)
Section titled “Profile header (default)”Loading Code Block...Profile header with context-switcher dropdown
Section titled “Profile header with context-switcher dropdown”Set hasDropdown: true to render a context-switcher (e.g. branch picker) inside the header. The dropdown is implemented with the design-system DropdownMenu component.
Loading Code Block...Logo header
Section titled “Logo header”Use headerType: 'logo' for a single brand image. The align prop controls horizontal alignment.
Loading Code Block...No header
Section titled “No header”Omit the prop entirely to render the sidebar with no header — the menu starts at the top.
Loading Code Block...Custom footer
Section titled “Custom footer”The React renderFooter prop and Vue <slot name="footer"> give you full control over the footer markup. When provided they take precedence over sidebarFooter / the footer prop.
Loading Code Block...The Vue footer prop accepts both Vue-style ({ type: 'branding', logo, name } or { type: 'menu', menu }) and React-style ({ variant: 'image', image } or { variant: 'list', list }) shapes for parity.
| Props | Default | Type | Description |
|---|---|---|---|
| sidebarHeader | - | SidebarHeader | undefined | Configuration for the sidebar header. Discriminated union — see the Sidebar Header section. Omit for no header. |
| menu | [] | array | An array of section objects representing the sidebar menu. Author with the React keys (`sectionLabel`, `children`) — Vue additionally accepts the legacy `title` / `items` aliases, but React does not. |
| sidebarFooter | - | object | Configuration for the sidebar footer section. |
| renderFooter | - | () => ReactNode | Render-prop alternative to `sidebarFooter`. When provided, takes precedence and gives full control over footer markup (equivalent to Vue's `<slot name="footer">`). |
| indentedSidebar | false | boolean | Adds a small left margin to nested items. Useful for visually distinguishing sub-items. |
React consumers can also set the desktop width via the
—sidebar-width CSS variable (range: 256px–380px) on the
sidebar’s container.
Sidebar Header
Section titled “Sidebar Header”The header prop is a discriminated union keyed by headerType. Common fields are listed first; variant-specific fields follow.
type SidebarHeader = | { headerType?: "profile"; // optional, defaults to "profile" variant?: "side-by-side" | "stacked"; title?: string; description?: string; image?: string; hasDropdown?: boolean; dropdownOptions?: { options: Array<{ label: string; value: string | object }>; }; dropdownPlaceholder?: string; onDropdownChange?: (value: string | object) => void; } | { headerType: "logo"; image: string; alt?: string; align?: "left" | "center" | "right"; } | undefined; // omit for no header| Props | Default | Type | Description |
|---|---|---|---|
| headerType | 'profile' | 'profile' | 'logo' | Discriminator for the header variant. Defaults to 'profile' for backwards compatibility. |
| variant | 'side-by-side' | 'side-by-side' | 'stacked' | Sub-mode for the profile header. 'side-by-side' renders avatar + text horizontally; 'stacked' renders them vertically. |
| title | - | string | The title text for the profile header. |
| description | - | string | The description text for the profile header. |
| image | - | string | Image URL. Required for `headerType: 'logo'`; optional avatar source for `headerType: 'profile'`. |
| align | 'left' | 'left' | 'center' | 'right' | Horizontal alignment for `headerType: 'logo'` only. |
| hasDropdown | false | boolean | Profile-only. When true, renders a context-switcher `<DropdownMenu />` inside the header. |
| dropdownOptions | - | { options: Array<{ label: string; value: string | object }> } | Profile-only. Options for the header dropdown. Required when `hasDropdown` is true. |
| dropdownPlaceholder | 'Select' | string | Profile-only. Placeholder text for the header dropdown trigger. |
| onDropdownChange | - | (value: string | object) => void | Profile-only. Fires when the user picks a different option in the header dropdown. The callback receives the **selected option's `value`** (not the full option object). |
Menu sections
Section titled “Menu sections”Each entry in the menu array is a section. Both naming conventions are accepted; React keys are preferred and Vue keys are aliased.
| Props | Default | Type | Description |
|---|---|---|---|
| sectionLabel | - | string | The label text for the menu section. Aliased as `title` in Vue (deprecated). |
| children | [] | array | Menu items inside this section. Aliased as `items` in Vue (deprecated). |
Menu items
Section titled “Menu items”| Props | Default | Type | Description |
|---|---|---|---|
| title | - | string | The display text for the menu item. Aliased as `label` in Vue (deprecated). |
| url | - | string | The destination URL. Aliased as `href` in Vue (deprecated). |
| isActive | false | boolean | Whether the item represents the user's current route. Aliased as `active` in Vue (deprecated). |
| icon | - | ReactNode (React) | FunctionalComponent | VNode | string (Vue) | Optional icon rendered to the left of the label. Vue additionally accepts a URL/path string — rendered as `<img :src>` inside the icon slot; React requires a `ReactNode`. |
| children | - | SidebarItem[] | Optional nested items. Renders the parent as a collapsible group. Aliased as `items` in Vue (deprecated). |
| disabled | false | boolean | Disables the item — applies `opacity-50`, `pointer-events-none`, and `aria-disabled="true"`. |
Sidebar Footer
Section titled “Sidebar Footer”The footer prop accepts both Vue-style ({ type: 'branding' | 'menu' }) and React-style ({ variant: 'list' | 'image' }) shapes. React consumers can also pass renderFooter for full custom markup; Vue consumers can use the <slot name="footer"> (see Custom footer).
| Props | Default | Type | Description |
|---|---|---|---|
| variant | 'list' | 'list' | 'image' | The visual variant of the footer. |
| list | [] | array | Footer items rendered for `variant: 'list'`. Each entry uses the same shape as a menu item (`title`, `url`, optional `icon`). |
| image | - | string | Image URL rendered for `variant: 'image'`. |
Accessibility
Section titled “Accessibility”- The nested hierarchy of the sidebar is semantically structured to be navigated via keyboard (
TabandShift + Tab), with active states distinctly highlighted. - Text contrast ratios exceed standard accessibility checks to ensure readability against the primary dark background colors.
- Interactive elements like dropdowns and expandable accordion menus emit proper ARIA roles when expanded or collapsed.