Stable

Bottom Sheet

Bottom sheets are surfaces containing supplementary content that are anchored to the bottom of the screen. They provide access to supplementary content and actions while keeping the main screen content visible.

Overview

Unlike Dialogue, BottomSheet has no open prop of its own. It renders a native <dialog> element and calls its showModal() as soon as it mounts — so visibility is controlled by whether the component is mounted at all, not by a boolean prop. Wrap it in an {#if open} block and flip open to false from the close callback.

The sheet's height is draggable via the handle at the top (mouse or touch) and resizable with the mouse wheel. Dragging it below a minimum height calls close('low').

Import

import { BottomSheet } from '@noxlovette/material';

Live Demo

See it live, with Controls, in Storybook rather than a hand-rolled preview here.

widgets

Playground

Open the Bottom Sheet story with a MenuItem action list inside.

Basic Usage

<script lang="ts">
  import { BottomSheet, MenuItem } from '@noxlovette/material';

  let open = $state(false);
</script>

<button onclick={() => (open = true)}>Open actions</button>

{#if open}
  <BottomSheet close={() => (open = false)}>
    <MenuItem iconProps={{ name: 'share' }}>Share</MenuItem>
    <MenuItem iconProps={{ name: 'link' }}>Copy link</MenuItem>
  </BottomSheet>
{/if}

BottomSheet Props

PropTypeDefaultDescription
children required
SnippetThe content rendered inside the sheet, below the drag handle — typically a list of actions or supplementary information.
close required
(reason: 'esc' | 'click' | 'low') => voidCalled when the sheet should close: 'esc' (Escape key), 'click' (clicking the backdrop), or 'low' (dragged/scrolled below a minimum height). The consumer is responsible for actually unmounting the component in response.

Accessibility

block

Native modal semantics

Built on the native <dialog>.showModal(), so it gets a built-in top-layer focus trap and Escape-to-dismiss for free from the browser.

keyboard

Escape handling

The native cancel event (Escape) is intercepted and preventDefault()-ed so the sheet can animate out via close("esc") instead of disappearing instantly.

drag_handle

Drag handle affordance

The grab-handle bar at the top is a purely visual/pointer affordance — keyboard users can still dismiss via Escape or by activating a close control in the sheet content.