Vize

Sidebar

Accessible, unstyled collapsible application sidebar with rail and mobile-sheet modes.

Package @vizejs/ui/sidebar
Maturity stable
Own the source vize lib pull sidebar
Requires context, controllable-state, dialog, id, primitive, shortcut
Aliases sidebar, app sidebar, context panel, navigation rail, off-canvas nav
Covers shadcn/ui Sidebar, HTML aside landmark, WAI-ARIA dialog pattern

Usage

import { SidebarProvider, Sidebar, SidebarRoot, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupLabel, SidebarHeader, SidebarInset, SidebarRail, SidebarTrigger } from "@vizejs/ui/sidebar";

Or copy the source into your project with vize lib pull sidebar (see Source Distribution).

API

SidebarProvider

Source: src/families/layout/sidebar/sidebar-provider.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned base id. null and undefined select a deterministic fallback.
open boolean undefined Controlled desktop open state. undefined selects uncontrolled behavior.
defaultOpen boolean true Initial desktop open state for uncontrolled use.
openMobile boolean undefined Controlled mobile sheet open state. undefined selects uncontrolled behavior.
defaultOpenMobile boolean false Initial mobile sheet open state for uncontrolled use.
collapsible SidebarCollapsible "offcanvas" Desktop collapse mode: off-canvas, icon rail, or never.
side SidebarSide "left" Screen edge the sidebar is attached to.
variant SidebarVariant "sidebar" Consumer styling variant mirrored to data-variant.
storage SidebarStorage undefined Adapter that persists the desktop open state. It is read only after mount, so server and hydration markup always start from open/defaultOpen.
storageKey string "vize-sidebar-open" Key used with storage.
keyboardShortcut string | null "Mod+B" Document-level shortcut that toggles the sidebar. null disables it.
mobileQuery string | null "(max-width: 767px)" Media query that switches to the mobile sheet. Evaluated only on the client; server rendering assumes desktop. null disables the sheet.
width string "16rem" Expanded width published as --vize-sidebar-width.
widthIcon string "3rem" Rail width published as --vize-sidebar-width-icon.
widthMobile string "18rem" Mobile sheet width published as --vize-sidebar-width-mobile.

Events

Event Payload Description
update:open [value: boolean] Fired when the desktop open state requests a controlled value.
update:openMobile [value: boolean] Fired when the mobile sheet requests a controlled value.
open-change [value: boolean, previous: boolean, nativeEvent: Event | null] Fired after any distinct desktop open request.

Slots

Slot Slot props Description
default SidebarSlotState Sidebar layout: SidebarRoot, SidebarInset, and triggers.

Exposed

Member Type Description
open boolean Desktop open state.
state SidebarState Desktop state token.
isMobile boolean Whether the mobile query currently matches. Always false during SSR.
openMobile boolean Whether the mobile sheet is open.
collapsible SidebarCollapsible Desktop collapse mode.
side SidebarSide Attached screen edge.
variant SidebarVariant Styling variant.
sidebarId string Id of the sidebar landmark, wired to trigger aria-controls.
setOpen (value: boolean, event?: Event | null) => boolean Request a desktop open value and report whether it differs.
setOpenMobile (value: boolean, event?: Event | null) => boolean Request a mobile sheet open value and report whether it differs.
toggle (event?: Event | null) => boolean Toggle the mobile sheet on mobile, otherwise the desktop sidebar.

Source: src/families/layout/sidebar/sidebar-root.vue

Props

Prop Type Default Description
ariaLabel string "Sidebar" Accessible name of the complementary landmark and the mobile sheet.
to string | HTMLElement "body" CSS selector or element the mobile sheet is moved into.
portalDisabled boolean false Render the mobile sheet in place instead of teleporting it.

Slots

Slot Slot props Description
default SidebarSlotState Sidebar contents. Receives the current Sidebar state.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarRoot

Source: src/families/layout/sidebar/sidebar-root.vue

Props

Prop Type Default Description
ariaLabel string "Sidebar" Accessible name of the complementary landmark and the mobile sheet.
to string | HTMLElement "body" CSS selector or element the mobile sheet is moved into.
portalDisabled boolean false Render the mobile sheet in place instead of teleporting it.

Slots

Slot Slot props Description
default SidebarSlotState Sidebar contents. Receives the current Sidebar state.

Exposed

Member Type Description
element HTMLElement | null Rendered desktop landmark, or null while rendered as a mobile sheet.

SidebarContent

Source: src/families/layout/sidebar/sidebar-content.vue

Props

Prop Type Default Description
as PrimitiveAs "div" Element or component to render.

Slots

Slot Slot props Description
default — Scrollable main area of the sidebar.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarFooter

Source: src/families/layout/sidebar/sidebar-footer.vue

Props

Prop Type Default Description
as PrimitiveAs "div" Element or component to render.

Slots

Slot Slot props Description
default — Sticky bottom area of the sidebar.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarGroup

Source: src/families/layout/sidebar/sidebar-group.vue

Props

Prop Type Default Description
id string | null undefined Consumer-owned group id. null and undefined select a deterministic fallback.

Slots

Slot Slot props Description
default — SidebarGroupLabel and group contents.

Exposed

Member Type Description
element Element | null Rendered element or component instance.
labelId string Id consumed by SidebarGroupLabel and wired to aria-labelledby.

SidebarGroupLabel

Source: src/families/layout/sidebar/sidebar-group-label.vue

Props

Prop Type Default Description
as PrimitiveAs "div" Element or component to render, for example a heading.

Slots

Slot Slot props Description
default — Visible group label.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarHeader

Source: src/families/layout/sidebar/sidebar-header.vue

Props

Prop Type Default Description
as PrimitiveAs "div" Element or component to render.

Slots

Slot Slot props Description
default — Sticky top area of the sidebar.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarInset

Source: src/families/layout/sidebar/sidebar-inset.vue

Props

Prop Type Default Description
as PrimitiveAs "main" Element or component rendered for the main content beside the sidebar.

Slots

Slot Slot props Description
default — Main application content.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

SidebarRail

Source: src/families/layout/sidebar/sidebar-rail.vue

Props

Prop Type Default Description
ariaLabel string "Toggle sidebar" Accessible name when no visible label supplies one.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before toggling. Call preventDefault() to keep state unchanged.

Slots

Slot Slot props Description
default SidebarSlotState Button contents. Receives the current Sidebar state.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
focus —

SidebarTrigger

Source: src/families/layout/sidebar/sidebar-trigger.vue

Props

Prop Type Default Description
ariaLabel string "Toggle sidebar" Accessible name when no visible label supplies one.

Events

Event Payload Description
click [nativeEvent: MouseEvent] Fired before toggling. Call preventDefault() to keep state unchanged.

Slots

Slot Slot props Description
default SidebarSlotState Button contents. Receives the current Sidebar state.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
focus —

Behavior

Normative behavior for the @vizejs/ui/sidebar compound primitive (application sidebar / context panel). Every row is proven by the named mounted-DOM, SSR, or compile-time test.

State x input Observable outcome Proven by
any desktop render Root is a labelled <aside> with a deterministic id, data-state, data-side, data-variant; groups are role="group" labelled by their label; inset is <main>; the provider publishes --vize-sidebar-width, --vize-sidebar-width-icon, --vize-sidebar-width-mobile. renders a labelled complementary landmark, sections, and CSS width variables
collapsible="offcanvas", trigger click Toggles open; the trigger mirrors aria-expanded/aria-controls; the collapsed landmark gets inert and data-collapsible="offcanvas"; update:open and open-change report the request. trigger toggles an off-canvas sidebar and makes the collapsed landmark inert
collapsible="icon", rail click Collapses to a rail that stays interactive (no inert); the rail is a tabindex="-1" button because the trigger is the keyboard path. icon collapse keeps the rail interactive and the rail toggles the sidebar
collapsible="none" The sidebar is always expanded, desktop toggles are disabled, and nothing is emitted. collapsible none keeps the sidebar expanded and disables toggles
controlled open; trigger click prevented Requests are emitted while state follows the prop; a prevented click does not toggle. controlled open waits for the parent and click is preventable
storage adapter The persisted value is read only after mount and each desktop change is written back under storageKey. persisted state is restored after mount and written on change
keyboardShortcut (default Mod+B) The document shortcut toggles the sidebar and consumes the key; null disables it. the Mod+B shortcut toggles the sidebar and can be disabled
mobileQuery matches after mount The root renders as a modal Dialog sheet labelled like the landmark; the trigger drives openMobile (update:openMobile) and Escape closes it; leaving the query restores the <aside> and listeners are released on unmount. mobile query renders the sidebar as a modal sheet toggled by the trigger
provider expose open, openMobile, isMobile, state, side, variant, sidebarId, setOpen, setOpenMobile, and toggle are available. provider exposes typed state and programmatic controls
parts outside a provider Mounting throws VIZE_UI_CONTEXT_MISSING; a group label outside a group names the missing SidebarGroup provider. sidebar parts require a provider
SSR Isolated requests render byte-identical desktop markup (SSR assumes desktop and ignores storage), including inert for a collapsed off-canvas sidebar. renders byte-identical desktop markup across isolated SSR requests
hydration with storage Hydration reuses server nodes with zero warnings, then applies the persisted state. hydrates without mismatches before applying storage and the mobile query
public types Collapse mode, side, variant, and storage adapter are closed, typed contracts. src/families/layout/sidebar/sidebar.types.test-d.ts
DOM/SSR/Vapor Every part compiles in each renderer lane. scripts/check-renderers.ts

Components

Component Contract
sidebar-provider.vue Owns desktop and mobile state, persistence, the shortcut, the mobile query, and width variables.
sidebar-root.vue Renders the <aside> landmark on desktop or a modal Dialog sheet on mobile.
sidebar-trigger.vue Native button that toggles the sidebar (mobile sheet on mobile) with aria-expanded/aria-controls.
sidebar-rail.vue Pointer hit area on the sidebar edge that toggles it; removed from the tab order.
sidebar-header.vue Header section with data-state.
sidebar-content.vue Scrollable content section with data-state.
sidebar-footer.vue Footer section with data-state.
sidebar-group.vue role="group" wrapper labelled by its SidebarGroupLabel.
sidebar-group-label.vue Label whose id labels the enclosing group.
sidebar-inset.vue Main content region (<main> by default) beside the sidebar.

Sidebar ships no stylesheet. Consumers style data-state, data-collapsible, data-side, data-variant, data-mobile, and the width variables.