Bottom Sheet Dialog
Mobile-native bottom sheet using native <dialog> element. Action menus, share sheets, and option lists that slide up from the bottom.
Overview
A bottom sheet is a dialog that slides up from the bottom of the viewport. It uses data-position="bottom" on a native <dialog> to get full-width, rounded-top-corners styling with safe-area padding for mobile devices.
Key features:
- Native
<dialog>with focus trapping and escape key - Full viewport width, max 85dvh height
- Rounded top corners with slide-up animation
- Automatic safe-area padding for home indicators
- Zero JavaScript with Invokers API
Action Sheet
A common mobile pattern: tapping an item reveals a list of contextual actions.
<button commandfor="actions" command="show-modal"> Options</button> <dialog id="actions" data-position="bottom"> <header data-layout="cluster" data-layout-justify="between"> <h2>Photo Options</h2> <button commandfor="actions" command="close" class="ghost icon-only" aria-label="Close"> <icon-wc name="x"></icon-wc> </button> </header> <section> <nav aria-label="Actions"> <ul role="list"> <li><a href="#"><icon-wc name="share"></icon-wc> Share</a></li> <li><a href="#"><icon-wc name="download"></icon-wc> Save to device</a></li> <li><a href="#"><icon-wc name="copy"></icon-wc> Copy link</a></li> <li><a href="#"><icon-wc name="bookmark"></icon-wc> Add to favorites</a></li> <li><hr></li> <li><a href="#" style="color: var(--color-error);"> <icon-wc name="trash-2"></icon-wc> Delete </a></li> </ul> </nav> </section></dialog>
Drag Handle
Add a visual drag handle indicator using a pseudo-element. This signals to mobile users that the sheet can be dismissed.
/* Visual drag handle at top of bottom sheet */dialog[data-position="bottom"]::before { content: ''; display: block; width: 2.5rem; height: 0.25rem; background: var(--color-border-strong); border-radius: var(--radius-full); margin: var(--size-s) auto var(--size-xs);}
Share Sheet
A share sheet pattern with a grid of share targets, similar to the native iOS/Android share UI.
<dialog id="share-sheet" data-position="bottom"> <header data-layout="cluster" data-layout-justify="between"> <h2>Share</h2> <button commandfor="share-sheet" command="close" class="ghost icon-only" aria-label="Close"> <icon-wc name="x"></icon-wc> </button> </header> <section> <layout-grid data-layout-min="4rem" data-layout-gap="m" style="text-align: center;"> <a href="#"> <icon-wc name="message-circle"></icon-wc> <small>Message</small> </a> <a href="#"> <icon-wc name="mail"></icon-wc> <small>Email</small> </a> <a href="#"> <icon-wc name="copy"></icon-wc> <small>Copy</small> </a> <a href="#"> <icon-wc name="bookmark"></icon-wc> <small>Save</small> </a> </layout-grid> </section></dialog>
Drag to Dismiss
Add data-gesture="dismiss-down" to enable swipe-down-to-close. The gesture library tracks the vertical drag, applies opacity falloff, and calls dialog.close('dismiss') when the threshold is reached. Buttons and links remain interactive.
<dialog id="actions" data-position="bottom" data-gesture="dismiss-down"> <header data-layout="cluster" data-layout-justify="between"> <h2>Options</h2> <button commandfor="actions" command="close" class="ghost icon-only" aria-label="Close"> <icon-wc name="x"></icon-wc> </button> </header> <section> <nav aria-label="Actions"> <ul role="list"> <li><a href="#">Action 1</a></li> <li><a href="#">Action 2</a></li> </ul> </nav> </section></dialog> <script> // Detect drag-dismiss vs explicit close document.getElementById('actions') .addEventListener('close', (e) => { if (e.target.returnValue === 'dismiss') { console.log('Dismissed by swipe'); } });</script>
The gesture is lazy-loaded and only ships when [data-gesture] attributes are present. Combine with the drag handle CSS (above) for a complete mobile experience.
Usage Notes
- Invokers API: Use
commandfor+command="show-modal"for declarative control. Fall back toshowModal()for older browsers. - Safe areas: Bottom padding is automatic via
var(--safe-bottom)for devices with home indicators. - Scrolling: Long content scrolls within the sheet. The
overscroll-behavior: containrule prevents scroll chaining to the page. - Backdrop close: Add a click listener on the dialog for backdrop dismissal (not built-in to native dialog).
- Animation: Uses
vb-slide-in-bottomkeyframes. Respectsprefers-reduced-motion.
Related
Dialog Element
Native dialog documentation
Drawer Dialog
Side-panel drawer patterns
Modal Dialog
Centered modal patterns
Mobile Bottom Sheet
Bottom sheet in mobile context