Skip to content

BbOffCanvas

Shows side-panel overlay content outside normal layout flow.

import { BbOffCanvas } from 'bitboss-ui';

On this page

Props

NameTypeDefaultDescription
descriptionstring | undefined-

One short line under the title, in the header — the shadcn DialogDescription shape: same block as the title, lower hierarchy, muted. It is also what aria-describedby points at. That wiring was dropped in v3 along with the old description prop, on the reasoning that pointing it at arbitrary body content would read whole forms aloud — true, and the reason it aims at THIS element only. Keep it to a sentence; anything longer belongs in the body.

disabledboolean | undefinedfalse

Disable EVERY user-initiated dismissal: backdrop click, Escape, drag-to-dismiss AND the header close (×) button (denied attempts play the deny nudge). Use it while an operation is in flight (e.g. a save) so the drawer cannot be dismissed mid-work. Compare persistent, which blocks backdrop/Escape but leaves the × working. Programmatic close (v-model) is still allowed.

Guards dismissal only — the drag included. The fields and buttons inside stay live, so disable them yourself while a save is in flight.

See example
draggableboolean | undefinedfalse

Enable drag-to-dismiss via VueUse useSwipe (fixed ~50px threshold toward the exit edge, including from the scrollable body once it is at its scroll edge). A grab handle on the inner edge is the visual cue. When false, the panel is static (dismiss via the close button, backdrop, or Escape only). A gesture that starts inside an element marked data-bb-no-drag never drags the panel — for content with drag interactions of its own.

A quarter of the extent, or a fast flick toward the edge, dismisses; anything shorter 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
eagerboolean | undefinedfalse

Render offcanvas content immediately instead of waiting for the first open.

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

See example
focusTargetstring | undefined-

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
fullscreenboolean | "mobile" | undefined-

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

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

See example
hideCloseboolean | undefinedfalse

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. Note that a panel with no title and no header slot has no close button to hide in the first place.

See example
modelValueboolean | undefinedfalse

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

persistentboolean | undefinedfalse

Prevent closing via outside clicks, Escape key or drag-to-dismiss. The header close (×) button STILL closes a persistent drawer — that is the documented escape hatch; combine with hideClose to remove it, or use disabled to block every dismissal. Programmatic close is still allowed.

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
ptPtMap<BbOffCanvasPtPart, BbOffCanvasPtState> | undefined-

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

pt:closePtValue | undefined-
pt:close:fullscreenPtValue | undefined-
pt:close:openPtValue | undefined-
pt:contentPtValue | undefined-
pt:content:fullscreenPtValue | undefined-
pt:content:openPtValue | undefined-
pt:descriptionPtValue | undefined-
pt:description:fullscreenPtValue | undefined-
pt:description:openPtValue | undefined-
pt:footerPtValue | undefined-
pt:footer:fullscreenPtValue | undefined-
pt:footer:openPtValue | undefined-
pt:headerPtValue | undefined-
pt:header:fullscreenPtValue | undefined-
pt:header:openPtValue | undefined-
pt:rootPtValue | undefined-
pt:root:fullscreenPtValue | undefined-
pt:root:openPtValue | undefined-
pt:titlePtValue | undefined-
pt:title:fullscreenPtValue | undefined-
pt:title:openPtValue | undefined-
side"left" | "right" | "top" | "bottom" | undefined"left"

Which viewport edge the offcanvas docks to (and slides in from).

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
sizeResponsive<OffCanvasSize> | undefined"sm"

Controls the maximum size of the offcanvas panel. Accepts named presets from 'xs' to '2xl', 'auto', a custom CSS size string, or a numeric pixel value — or a per-breakpoint map (e.g. { default: 'sm', lg: 'lg' }) to switch responsively.

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
stackstring | undefined-

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
stackGapnumber | undefined60

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. Only the top two open panels keep a dimmed and blurred backdrop; deeper ones go transparent, so a deep stack does not read as layers of dimming.

See example
titlestring | undefined-

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, unlike BbDialog, no floating close button either.

See example
transitionDurationnumber | undefined250

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.

NameTypeDescription
modelValueboolean | undefined

The only way to open a panel. There is no exposed open(), and vetoing a close from @hide is not the way to keep it open — that is persistent.

See example

Events

NameTypeDescription
hidden(event: "hidden"): void
hide(event: "hide"): void
show(event: "show"): void

Fires as the model turns true, before the slide. The hook for reseeding a draft so Cancel is a real discard.

See example
shown(event: "shown"): void
update:modelValue(event: "update:modelValue", value: boolean): void

Slots

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

NameTypeDescription
default{ close: () => void; }

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
descriptionBbOffCanvasDescriptionSlotProps

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.

footerobject

Content rendered in the panel footer, below the body area. Typically used for action buttons.

Stays pinned while the body scrolls. One primary action — Apply, Save, Assign — with its counterweight beside it.

See example
headerBbOffCanvasHeaderSlotProps

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 or #description goes.

See example
titleBbOffCanvasTitleSlotProps

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.

Changes from v2

Props removed or renamed in 3.0. If you are coming from v2, the answer is here.

  • compactremovedfails silently
  • directionsidefails silently
  • showClosehideClosefails silently