svelte-base-drawer

A Svelte 5 port of Base UI's Drawer (v1.6.0), built on bits-ui Dialog. Swipe to dismiss with momentum, snap points, nested drawers, swipe to open, virtual keyboard support. Unstyled — you own the CSS. MIT licensed, not affiliated with MUI.

Install

npm install svelte-base-drawer

bits-ui is a peer dependency: the drawer wraps its Dialog for focus management, portals and accessibility. If your project doesn't already use it, install it as well: npm install bits-ui.

Usage

The anatomy mirrors Base UI. Drawer.Viewport is required — it hosts all swipe and touch-scroll handling. Components ship unstyled: import svelte-base-drawer/drawer.css as a starter stylesheet, or style the data attributes yourself (each demo below has its own CSS).

<script>
  import * as Drawer from 'svelte-base-drawer';
</script>

<Drawer.Root>
  <Drawer.Trigger>Open</Drawer.Trigger>
  <Drawer.Portal>
    <Drawer.Backdrop />
    <Drawer.Viewport>          <!-- required: hosts all swipe handling -->
      <Drawer.Popup>           <!-- the panel -->
        <Drawer.Handle />
        <Drawer.Title>Title</Drawer.Title>
        <Drawer.Description>Description</Drawer.Description>
        <Drawer.Content>       <!-- the scrollable region -->
          Your content here
        </Drawer.Content>
        <Drawer.Close>Close</Drawer.Close>
      </Drawer.Popup>
    </Drawer.Viewport>
  </Drawer.Portal>
</Drawer.Root>

Basic drawer

Swipe down to dismiss, or tap the backdrop. Catch it mid-animation.

Snap points

Drag the sheet to snap between a compact peek and a near full-height view.

Nested drawers

Nested drawers stack with a scale effect while staying independently focus managed.

Virtual keyboard aware

On mobile, focused fields stay visible above the software keyboard.

Indent effect

The app surface scales down behind the drawer, iOS style.

Mobile navigation

A tall menu scrolled within the viewport. Flick down from the top to dismiss.

Swipe to open

Swipe from the right edge of the frame (or drag it with a mouse) to open the drawer.

Swipe from the right edge to open the drawer.

Action sheet

An uncontained drawer with a separate destructive action, iOS style.

Styling

The engine drives CSS custom properties (registered with inherits: false) and data attributes; your stylesheet decides what they do.

CSS variables

  • --drawer-swipe-movement-x / -y — displacement during the drag, in px (on the popup)
  • --drawer-swipe-progress — 0–1, how far toward dismiss (on the backdrop)
  • --drawer-swipe-strength — 0.1–1, velocity scalar for the dismiss transition duration
  • --drawer-snap-point-offset — offset of the active snap point (on the popup)
  • --drawer-keyboard-inset — software keyboard inset (requires VirtualKeyboardProvider)
  • --nested-drawers — number of open nested drawers (for stacking effects)

Data attributes

  • [data-swiping] — present while the user is dragging
  • [data-expanded] — present when snapped to the largest snap point
  • [data-nested] / [data-nested-drawer-open] — nesting state, for stacked-cards styling
  • [data-starting-style] / [data-ending-style] — enter/exit transition hooks (from bits-ui)
  • [data-swipe-ignore] — opt-out: no swipe ever starts on this element

MIT © Jérémy Le Mardelé. Ported from Base UI (MIT © Material-UI SAS) — demos adapted from the Base UI documentation.