MazBottomSheet
MazBottomSheet is a standalone component like a simple dialog but anchored at the bottom of the screen. Full-width on mobile and constrained/centered on desktop, with a header (icon, title, close button), a footer and many replaceable slots. Useful for mobile UX.
Before use it, you should install the MazUi plugin in your project, follow instructions in Getting Started
TIP
This component uses the <Teleport to="body"> with MazBackdrop, so you can implement this component anywhere and it inherits all its props (persistent, closeOnEscape, etc.)
Basic usage
The sheet has a header (with the title and a close button) and an optional footer slot. It opens full-width on mobile and is constrained/centered on desktop (see Max width).
Swipe to close (iOS-like)
By default a drag handle (grab bar) is shown at the top of the sheet, and you can close the sheet by dragging that handle down - the sheet follows your pointer and either dismisses (past the threshold) or snaps back. This works with both touch and mouse.
Disable it with :swipe-to-close="false" (the handle is then hidden too), or replace the handle with the #handle slot. A persistent sheet never dismisses on swipe: it snaps back instead.
Header with an icon
Pass an icon (an icon value or a full MazIconProps object) to display it on the left of the title.
Replaceable slots
Everything in the header is replaceable: use #icon and #title to customize parts of the default header, or #header to replace the whole header (you get the close function as a binding).
Max width
On mobile the sheet is always full-width. From the tablet breakpoint and up, it is constrained to max-width and centered horizontally. The default max-width is 35rem; pass the max-width prop (a MazSizeUnit) to override it.
Without header
Hide the whole header with hide-header, or only the close button with hide-close-button.
Persistent
A persistent sheet cannot be closed by clicking outside or pressing escape, and the close button is removed. Provide your own action to close it.
Full example
Nike Air Max
Premium Running Shoes
Accessibility
The bottom sheet is a modal dialog labelled by its title and described by its content. The focus is trapped inside while it is open, Esc closes it, and the rest of the page is inert (except the toasts and the live regions).
Props
| Name | Description | Type | Required | Default | Possible values |
|---|---|---|---|---|---|
| model-value | v-model Modal's model value | boolean | No | - | - |
| title | Title of the bottom sheet in the header | string | No | - | - |
| icon | Icon displayed on the left of the header. Accepts an icon value or a full MazIconProps object. | MazIconLike | No | - | - |
| max-width | Bottom sheet's max-width, applied from the tablet breakpoint and up (full-width below). | ``${number}rem|${number}px|${number}em|${number}vw|${number}vh|${number}vmin|${number}vmax|${number}%|${number}ch|${number}cm|${number}mm|${number}in|${number}ex|${number}pc|${number...` | No | "40rem" | - |
| hide-close-button | Remove the close button in the header | boolean | No | false | - |
| hide-header | Remove the whole header | boolean | No | false | - |
| padding | Add the padding on the content area | boolean | No | true | - |
| persistent | Persistent bottom sheet (not closable by clicking outside and remove close button) Persistent dialog (not closable by clicking outside and remove close button) | boolean | No | - | - |
| swipe-to-close | Show the drag handle at the top and allow closing the sheet by swiping it down (iOS-like). The swipe never closes a persistent sheet (it snaps back instead). | boolean | No | true | - |
| teleport-selector | Teleport selector | string | No | - | - |
| before-close | Function called before modal is close | (() => void | Promise<void>) | No | - | - |
| close-on-escape | Prevent close on escape key | boolean | No | true | - |
| transition-name | Transition name | string | No | - | - |
| backdrop-class | Backdrop class | ClassValue | No | - | - |
| backdrop-content-class | Backdrop content class | ClassValue | No | - | - |
| content-padding | Add padding to the content | boolean | No | - | - |
| justify | Justify content | "none" | "center" | "end" | "start" | "space-between" | "space-around" | No | - | 'none' | 'center' | 'end' | 'start' | 'space-between' | 'space-around' |
| align | Align content | "none" | "center" | "end" | "start" | No | - | 'none' | 'center' | 'end' | 'start' |
| variant | Variant | "bottom-sheet" | "dialog" | "drawer" | No | - | 'bottom-sheet' | 'dialog' | 'drawer' |
| aria-labelledby | ID for aria-labelledby | string | No | - | - |
| aria-describedby | ID for aria-describedby | string | No | - | - |
Events
| Event name | Payload | Description |
|---|---|---|
| update:model-value | value: boolean | Emitted when the model value is updated |
| open | value?: void | undefined | Emitted when the component is opened |
| close | value?: void | undefined | Emitted when the component is closed |
Slots
| Name | Description | Bindings |
|---|---|---|
| handle | Drag handle (grab bar) displayed at the top when swipeToClose is enabled | - |
| header | Header slot | close () => void - close function |
| icon | Icon slot in the header | - |
| title | Title slot in the header | - |
| default | Default content | close () => void - close function |
| footer | Footer slot | close () => void - close function |
Expose
close
Close the bottom sheet