Skip to content

BbOffCanvas

Shows a side panel; also the v-bb-off-canvas directive.

import { BbOffCanvas } from 'bitboss-ui';

On this page

Props

NameDescription
defaultData Type: Record<string, any>

What data is when an opening passes none (a create): an object, copied at once, so inputs bind data.x with no guard. An opening's data lays over it ({ ...defaultData, ...row }, one level). reset() restores its keys but keeps an edit's id; a close restores it.

The fresh copy a create gets as data, the base an opening's row is laid over, and what every close restores. reset() (a filters Reset) restores the keys it declares and keeps the rest.

See example
description Type: string

One short line under the title, muted (the shadcn DialogDescription shape), and the only element aria-describedby points at. Keep it to a sentence; anything longer belongs in the body.

draggable Type: booleanDefaultfalse

Drag-to-dismiss: a ~50px swipe toward the exit edge (also from the body once it is scrolled to its edge), with a grab handle as the cue. A gesture that starts inside data-bb-no-drag never drags the panel.

Dragging about 50px toward the edge dismisses; a shorter drag springs back. On a top or bottom sheet the gesture hands off to native scrolling first, so scrolling a long body never closes it.

See example
eager Type: booleanDefaultfalse

Keep the body mounted while closed, from before the first opening. Without it the body mounts per opening and unmounts after @hidden. data still clears while closed, so an eager body guards its reads.

The body renders lazily otherwise — nothing inside exists until the first open, which is what a test or a measurement runs into.

See example
focusTarget Type: string

CSS selector of the element to focus after opening. Defaults to the first tabbable element.

Chooses where focus starts, never whether it is contained: showModal() traps focus and returns it to the trigger either way.

See example
fullscreen Type: boolean | "mobile"

Display the offcanvas fullscreen. Use 'mobile' to restrict fullscreen to small devices.

Covers the whole viewport, edge to edge, unlike the dialog. fullscreen="mobile" is the usual pairing for a right-hand detail panel: sized on desktop, whole screen below the mobile breakpoint.

See example
hideClose Type: booleanDefaultfalse

Hides the default close (×) button in the header (e.g. for a persistent drawer you don't want dismissible — the × otherwise still closes a persistent drawer).

Inverted from v2's show-close, which defaulted to true; a leftover :show-close="false" falls through to $attrs and the × comes back. A headerless panel floats its × over the body corner, as the dialog does, and hide-close removes that one too.

See example
id Type: string

Names the panel for v-bb-off-canvas="'filters'" and useBbOffCanvasContext, found nearest to the trigger, so two pages may reuse an id. Also the DOM id: one panel per id.

One panel per id: it is also the DOM id. Many rows open the same panel with their own data rather than rendering one each.

See example
modelValue Type: booleanDefaultfalse

Used by v-model to open / close the panel. A panel with no v-model starts closed.

navigation Type: booleanDefaultfalse

Syncs the open state with the URL: opening writes ?<queryKey>=true, closing removes it, a URL with the key opens the panel on load, and Back closes it (refused whenever Escape is). Template panels only; keep a record id in your own query.

Writes ?offcanvas=true by default, so it never collides with a dialog's ?dialog=true. Back closes the panel like Escape.

See example
persistent Type: booleanDefaultfalse

Blocks closing by an outside click, Escape or drag-to-dismiss. The header close (×) STILL closes a persistent drawer, the documented escape hatch: add hideClose to remove it, or use preventClose to block every dismissal. Programmatic close still works.

Blocks the backdrop, Escape and the drag. The × still closes — that is the escape hatch — so pair it with hideClose when the choice must be made from the footer, and keep a visible Cancel there.

See example
preventClose Type: booleanDefaultundefined (follows a saving form inside)

Refuses every user close (backdrop, Escape, drag, the ✕, the slots' close) with the deny nudge; v-model still closes. Unset: locked while a BbForm inside saves (an async @submit). true: always; false: never, not even mid-save. Beside a form: busy || undefined.

Refuses every user close, the drag and the slots' close included. Rarely written: unset, the panel already locks itself while a BbForm inside it saves; false keeps it closable even mid-save. Close with complete(value) or hide() (or v-model) when the work is done.

See example
pt Type: PtMap<BbOffCanvasPtPart, BbOffCanvasPtState>

Passthrough, object form: the same keys as the pt:* attributes without the prefix. See the pt:<part> row.

pt:<part> Type: PtValue

Passthrough, attribute form: one attribute per part, pt:<part>, and per part and state, pt:<part>:<state>. Parts: close, content, description, footer, header, root, title. States: fullscreen, open.

See example
queryKey Type: stringDefault"offcanvas"

The query key navigation writes.

replace Type: booleanDefaultfalse

With navigation, replaces the history entry instead of pushing one, so Back leaves the page instead of closing the panel.

side Type: Responsive<"left" | "top" | "bottom" | "right">Default"left"

Which viewport edge the offcanvas docks to (and slides in from). Also a per-breakpoint map (e.g. { default: 'bottom', md: 'right' }), resolved when the panel opens: an open panel keeps its side through a resize.

Called direction in v2, and the rename is silent: a leftover direction falls into $attrs and the panel docks left. It also decides the drag axis, which dimension size means, and which edge a stacked parent peeks past.

See example
size Type: Responsive<OffCanvasSize>Default"sm"

The panel's extent along its axis: a left/right panel's width (shrinks with a narrower viewport) or a top/bottom one's height (capped at the viewport). A preset 'xs'–'2xl', 'auto', a CSS size, a pixel number, or a per-breakpoint map (e.g. { default: 'sm', lg: 'lg' }).

The extent along the panel's own axis, not a width: the same lg is 512px across on a right panel and 512px tall on a bottom one. auto is fit-content. The v3 presets are narrower than v2's { sm: 384, md: 652, lg: 896 } and nothing warns — pin them with offCanvasDefaultSizes if a layout assumed them.

See example
snap Type: BbSnapPoint

The snap stop the sheet rests at, written as one of the snapPoints entries (Q71.8). Updated once the sheet settles on another stop; setting it moves the sheet there. Unbound, every opening starts at the first stop.

snapPoints Type: BbSnapPoint[]

Heights a draggable bottom sheet rests at, smallest first: a fraction of the screen (0.5, 1 = full) or '240px'. The first is the opening height; v-model:snap holds the stop. Ignored on other sides and fullscreen (guide § Snap points).

A draggable bottom sheet only. It opens at the first stop, a release moves one stop at most, and only a drag below the first stop closes.

See example
stack Type: string

Name of the stack this drawer belongs to. Drawers sharing the same stack value step back behind one another as later ones open; drawers in different stacks never affect each other. When omitted, the drawer stacks with nothing.

Panels sharing a name step back and leave a peeking band — the opposite of BbDialog's stack, which hides the member underneath. The band only appears when the panels also share a side.

See example
stackGap Type: numberDefault60

Pixels each stacked parent drawer shifts inward when a child opens on top, leaving a peeking band of the parent visible.

How much of the parent stays visible behind a child. Every open panel dims the one beneath it and only the bottom one blurs; set --bb-overlay-above: transparent to keep a single dim.

See example
title Type: string

Title text announced to assistive technologies. If omitted, no header is rendered and accessibility must be handled manually.

The accessible name, not just a heading: it wires aria-labelledby. Without it and without a header slot there is no header at all, and the × floats over the body corner, as on BbDialog.

See example
transitionDuration Type: numberDefault250

Controls the duration of the open and close animations.

Times both the slide and when hidden fires. Reopening inside that window keeps the panel open rather than snapping it shut.

See example

v-model

Values kept in sync through v-model.

NameDescription
modelValue Type: boolean

For a panel your state opens; a button opens one by id with v-bb-off-canvas. Bound, it wins over the directive and show(). Vetoing a close from @hide is not the way to keep it open — that is persistent.

See example
snap Type: BbSnapPoint

Events

NameDescription
hidden Type: (): void

Emitted after the close transition completes and the offcanvas is fully dismissed.

hide Type: (result: BbDialogResult): void

Emitted as soon as the panel starts to close (model becomes false), with the opening's result: the same object its promise settles with, { completed: true, value } or { completed: false, reason } (Q73.6).

Fires as the close starts, with the opening's result, a swipe included: { completed: true, value } or { completed: false, reason }. To tell a save from a cancel, close a save with complete(), not by writing the model: on a v-model panel too it reports { completed: true }.

See example
show Type: (): void

Emitted as soon as the user triggers the open action (model becomes true).

Fires as the panel starts to open, before the slide, with the opening's data already set. Bind the fields to data instead of seeding a draft here: it is a fresh copy every opening, so closing without complete already discards.

See example
shown Type: (): void

Emitted once the open transition has run (symmetric with hidden): the panel is settled, so code that measures or anchors to its content sees the final layout. Not emitted for a panel closed before it finished opening.

update:modelValue Type: (value: boolean): void

Emitted with the new value whenever v-model changes.

update:snap Type: (value: BbSnapPoint | undefined): void

Emitted with the new value whenever v-model:snap changes.

Slots

The listed properties are the ones exposed to the slot scope.

NameDescription
default Type: BbOffCanvasDefaultSlotProps

Primary body content of the off-canvas panel, rendered in the scrollable body area.

The only region that scrolls, and on a draggable top or bottom panel it is also what absorbs a drag until it reaches its own edge.

See example
description Type: BbOffCanvasDescriptionSlotProps

Replaces the description text under the title. Renders the header even when title and description are unset — a slotted description is a description, the same rule #title follows.

header Type: BbOffCanvasHeaderSlotProps

Replaces the entire off-canvas header section (title + close button). Maintains accessibility wiring via the provided props.

Providing it renders a header even with no title. It replaces the ×, so render your own control wired to close, and put titleId on your heading or aria-labelledby points at nothing. This is where a v2 #close goes; a v2 description is the description prop or #description slot.

See example
title Type: BbOffCanvasTitleSlotProps

Replaces the default title text inside the header. Remains linked to the panel through aria-labelledby. Providing this slot renders the header even when title is unset — a slotted title is a title.

Renamed and removed

Names from v2 and from earlier 3.0 betas that no longer work, and what to write instead.

  • compactremovedfails silently
  • directionsidefails silently
  • showClosehideClosefails silently