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.
Header and footer
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
| Prop | Type | Default | Description |
|---|---|---|---|
items | (SidebarLink | SidebarSection)[] | — | Links, optionally grouped into labelled sections |
side | 'left' | 'right' | 'left' | Which edge carries the border |
label | string | 'Sidebar' | Accessible name for the navigation landmark |
unstyled | boolean | — | Drop built-in classes |
class | string | — | Merged 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
| Slot | Props | When 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
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.