Skip to content

Layout

ISidebar

The app's primary navigation column — sections, collapsible groups, badges, and a collapse-to-icons mode. It works with or without IAppShell; it is a column, and it needs a height.

A link with href renders an <a>. Omit it and you get a <button> instead, so onSelect can hand navigation to your router without a full page load.

Sections

An entry with a section key is a labelled run of links under a small heading. A collapsible group carries items under a label instead, which is what tells the two apart.

Links written before or between sections keep their position.

Collapsible groups

A link with its own items becomes a group that opens and closes in place. defaultOpen starts it open.

The panel animates its height, so the rows below slide rather than jump. Inside the group, the rule sits on the centre of the parent's icon and each child's label lines up with the parent's.

Collapse to icons

v-model:collapsed narrows the column to its icons. The labels are removed rather than visually hidden, and every link carries an aria-label in their place.

Badges and section headings fold away with the labels; the group chevron goes too, since there is no room to show what it would open.

Both slots stay pinned, with the link list as the only scrolling region. Each receives collapsed, so a wordmark can become a monogram.

A right-hand sidebar

side decides which edge carries the border. Pair it with IAppShell's sidebar-position to move the column itself.

Collapsed, in full

Props

PropTypeDefaultDescription
items(SidebarLink | SidebarSection)[]Links, optionally grouped into labelled sections
side'left' | 'right''left'Which edge carries the border
labelstring'Sidebar'Accessible name for the navigation landmark
unstyledbooleanDrop built-in classes
classstringMerged with the built-in classes
ui{ root?, header?, nav?, footer?, section?, sectionLabel?, link?, linkLabel?, linkBadge?, groupIcon?, groupContent?, groupInner? }Per-slot class overrides

v-model:collapsed is a boolean model, defaulting to false.

Slots

SlotPropsWhen to use it
default{ collapsed }Replace the whole link list
header{ collapsed }Wordmark, workspace switcher — pinned above the list
footer{ collapsed }Account row, version — pinned below the list
link{ link, collapsed }Render one link yourself, keeping the row chrome

Item shapes

ts
interface SidebarLink {
  label: string
  href?: string
  icon?: IconLike
  badge?: string | number
  disabled?: boolean
  active?: boolean
  onSelect?: () => void
  items?: SidebarLink[]
  defaultOpen?: boolean
}

interface SidebarSection {
  section: string
  items: SidebarLink[]
}

active is reflected as both data-active and aria-current, so a router integration only has to compute a boolean.