Skip to content

Bottom Sheet

Props ​

NameTypeDefaultDescription
labelstring-Accessible name for the sheet, and required. It is associated through aria-label; the panel has no built-in heading to derive a name from.
v-model:isOpenbooleanfalseControlled open state. Bound, the sheet renders exactly this value and Escape, a scrim click, or a swipe only asks for a change; unbound, the component owns its state.
heightBottomSheetHeight | number | string'capped'How tall the sheet is. Named budgets are hug (fits content, up to 92% of the viewport), capped (about 62%), and tall (about 92%); a number is pixels and a string is used as a CSS length. Content taller than the visible panel scrolls inside it.
snapPointsreadonly BottomSheetSnapPoint[]-Extra heights the sheet can rest at when dragged. A number is a viewport fraction, '50%' a percentage, and '320px' an absolute height; the sheet's own height is always the tallest stop. Without it the sheet only opens and closes.
paddingBottomSheetPadding-Inner padding of the content box using the spacing scale. When omitted, the theme decides, falling back to the --spacing-4 step (16px) on every logical edge; pass 0 for a flush content box. The content box is a container, so a lone child that carries its own inset escapes the padding.
purposeBottomSheetPurpose'info'Implicit dismissal, matching Dialog. info allows Escape, a scrim click, and a swipe; form allows Escape only; required blocks every implicit path and uses alertdialog semantics.
hasScrimbooleantrueWhether to render a scrim and open modally. true uses showModal(): top layer, focus confinement, page scroll lock, and an inert background. false uses show(), leaving the page interactive and scrollable.
finalFocusRefHTMLElement | nullnullElement that receives focus after the sheet closes, replacing the element that was focused when it opened. Use it when the opener can remount or the active element is not a reliable trigger.
isInlinebooleanfalseRenders the panel in the document flow instead of a <dialog>, without a scrim, focus trap, or motion. Used to preview the surface inside a container that is already inert, such as component documentation.

Slots ​

NameDescription
defaultThe sheet content, rendered in the scrolling area below the grab handle.

Events and template ref ​

NameSignatureDescription
openChange(isOpen: boolean) => voidEmitted when the sheet asks to change state: Escape, a scrim click, a swipe dismissal, or a v-model:isOpen write.
update:isOpen(isOpen: boolean) => voidHandled automatically by v-model:isOpen; you rarely need it directly.
motionStart(motion: 'entering' | 'exiting') => voidEmitted when an entrance or exit motion starts.
motionComplete(motion: 'entering' | 'exiting') => voidEmitted when the motion finishes. The exit completion is what closes the <dialog> and hands focus back.
snap(visibleHeight: number) => voidEmitted when a drag settles on a stop, with the sheet's visible height in pixels at that stop.
elementHTMLDivElement | nullThe panel element, exposed through a template ref. class and style land on this element.
focus() / blur()() => voidMoves focus into or out of the panel.

Native attributes ​

The root element is the panel <div> (class astryx-bottom-sheet), wrapped in a fixed-position <dialog>.

The following are passed to the panel element:

  • HTML attributes.
  • aria-* attributes, except aria-label and aria-labelledby, which name the dialog around it.
  • data-* attributes.
  • class.
  • style.