Sidebar

A collapsible, resizable application sidebar with header/footer slots and a drag-to-resize rail.

html
<UiSidebar />

Collapsible

collapsible is how the sidebar gets out of the way. Its default, icon, shrinks it to an icon-only strip that still navigates; offcanvas hides it altogether; none fixes it open and drops the rail entirely. The header, default and footer slots are all handed the current state, which is how the content below knows to render labels or not — click or drag the rail on the edge to see it.

JD
Jane Doe
Admin

Side

side moves the sidebar to the other edge of the screen. The rail and its collapse direction mirror along with it.

Rail

rail is the strip on the sidebar's edge that both toggles it (click) and resizes it (drag). Turning it off leaves the sidebar collapsible in principle but with no built-in way to do it, so pair a false rail with v-model:open and a control of your own. It never renders at all when collapsible is none, which is what the example below shows.

The rail handle both toggles (click) and resizes (drag) the sidebar — dragging past minWidth/maxWidth by more than ~40-60px snaps it collapsed/expanded instead of clamping.

Open

open takes the expanded/collapsed state out of the sidebar's hands. Bind it with v-model:open so the rail still works, or pass it one way to pin the sidebar and drive it entirely from elsewhere — which is the pairing below, where rail is off and the button is the only way through.

Default open

defaultOpen decides whether an uncontrolled sidebar starts expanded. It's true by default; set it false for a shell where the content is the point and the navigation is something you go looking for. Once the reader touches the rail the sidebar owns the state, so this only ever describes the first render.

Title

title is the name in the built-in header, shown instead of the default logo. It's ignored the moment you provide a header slot, which replaces that whole area — reach for the prop when a line of text is all you need, and the slot when the header has to hold a team switcher.

Bundy

Workspace

Description

description is the quieter second line under the title — the workspace, the environment, whatever qualifies the name above it. Both collapse away with the sidebar. The title and description slots below keep this header layout while replacing just the text, which is the middle ground between the props and the full header slot.

Bundy Pro

All systems normal

Close

close adds a close button to the header's actions area that collapses the sidebar. It's a second route to what the rail already does, worth adding where the rail is easy to miss; it does nothing at all when collapsible is none, since there's then nothing to collapse to.

Bundy

Workspace

Default width

defaultWidth is the pixel width the sidebar opens at. It's a starting point rather than a fixed size — the rail handle can drag it anywhere between minWidth and maxWidth from there.

Min width

minWidth is how narrow the rail handle can drag the sidebar. Set it to the width your narrowest label still fits in — dragging further doesn't squeeze past it, and pushing well beyond the bound snaps the sidebar collapsed instead, so the reader gets the icon strip rather than a cramped one.

Max width

maxWidth is the other bound — how wide the rail handle can pull the sidebar before it stops. Keep it modest: past a point the sidebar is just taking room from the content, and dragging hard past the bound snaps it fully expanded rather than growing further.

`collapsible="offcanvas"` — hides the sidebar completely instead of shrinking it to icons

Nested sub-items — children collapse away with the sidebar, since there's no room for them at icon width

items isn't a prop — the sidebar owns layout only; navigation content is entirely up to the consumer via the default slot, matching NuxtUI's separation of concerns.

The sidebar this app's own dashboard renders — a full composition, not a prop demo

Source: app/components/examples/DashboardSidebar.vue.

The sidebar has no height of its own — calc(100vh - 24px) is a *max*, not a fill. Its inner column is h-full, a percentage that resolves to auto unless an ancestor has a definite height, so on its own it sizes to its content. Put it in a stretching parent (<div class="flex min-h-screen">, as this app's layout does) to get a full-height app rail; the footer only pins to the bottom once something gives it height.


API Reference

Generated from the component's source — props, slots and emits as the component actually declares them.

Props

Prop
Type
Default
Description
"offcanvas" | "icon" | "none"
'icon'
The collapse behavior of the sidebar. - `icon`: shrinks to icon-only width. - `offcanvas`: hides completely. - `none`: not collapsible; the rail is never shown.
"left" | "right"
'left'
The side to render the sidebar on.
boolean
true
Display a rail on the sidebar edge to toggle collapse. Only renders when `collapsible` is not `none`.
boolean
Controls whether the sidebar is expanded. Omit this to let the sidebar manage its own state internally (starting from `defaultOpen`); pass it to fully control it yourself.
boolean
true
Whether the sidebar starts expanded when uncontrolled.
string
Title displayed in the header. Ignored when the `header` slot is used.
string
Description displayed below the title. Ignored when the `header` slot is used.
boolean
false
Shows a close button in the header's actions area that collapses the sidebar. Only has an effect when `collapsible` is not `none`.
number
208
The width, in pixels, the sidebar starts at when expanded. Draggable via the rail handle.
number
180
The minimum width, in pixels, the rail handle can drag the sidebar down to.
number
400
The maximum width, in pixels, the rail handle can drag the sidebar up to.

Slots

Slot
header
title
description
default
footer
rail

Emits

Event
Payload
Description
update:open
[value: boolean]

Types

ts
type SidebarState = "expanded" | "collapsed";