npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

svelte-base-drawer

v0.1.1

Published

Drawer component for Svelte 5 — a port of Base UI's Drawer built on bits-ui Dialog. Swipe to dismiss, snap points, nested drawers, swipe to open, virtual keyboard support.

Readme

svelte-base-drawer

A Svelte 5 port of Base UI's Drawer (v1.6.0), built on bits-ui Dialog.

A drawer (bottom sheet) with mobile-grade gesture handling: the swipe engine, touch-scroll arbitration and release physics are a faithful port of Base UI's useSwipeDismiss, while focus management, portals and accessibility come from bits-ui Dialog.

Unofficial port — not affiliated with MUI or the Base UI team. MIT licensed, like the original.

Features

  • Swipe to dismiss with momentum: velocity-scaled exit transitions, catchable mid-animation, scroll-vs-swipe arbitration inside scrollable content
  • Snap points — controllable via bind:snapPoint, with snapToSequentialPoints and data-expanded
  • Nested drawers — stacked-cards styling via --nested-drawers and --drawer-frontmost-height
  • Swipe to open from a screen edge (Drawer.SwipeArea)
  • Indent effect — the app surface scales down behind the drawer, iOS style (Drawer.Provider + Drawer.Indent)
  • Virtual keyboard support — focused fields stay visible above the software keyboard (Drawer.VirtualKeyboardProvider)
  • 4 swipe directions (down, up, left, right), unstyled by default, CloseWatcher support on Android

Install

bits-ui is a peer dependency:

npm install svelte-base-drawer bits-ui

Requires Svelte 5.

Usage

<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>

The anatomy mirrors Base UI:

| Component | Role | | --------------------------------------------------- | ------------------------------------------------------------------------------------- | | Drawer.Root | State container. bind:open, bind:snapPoint, snapPoints, swipeDirection | | Drawer.Trigger | Opens the drawer (bits-ui re-export) | | Drawer.Portal | Portals the drawer to document.body or a custom container (to={...}) | | Drawer.Backdrop | Dimmed overlay behind the drawer | | Drawer.Viewport | Required. Fixed full-screen container hosting all swipe and touch-scroll handling | | Drawer.Popup | The panel itself. trapFocus={false} / preventScroll={false} for non-modal drawers | | Drawer.Handle | Grab handle | | Drawer.Content | The scrollable region (scrolling here doesn't drag the drawer until it hits an edge) | | Drawer.Title / .Description / .Close | bits-ui re-exports | | Drawer.SwipeArea | Edge zone that opens the drawer with a swipe | | Drawer.Provider + .Indent / .IndentBackground | Opt-in iOS-style scale-down of the app surface | | Drawer.VirtualKeyboardProvider | Opt-in: keeps focused fields visible above the mobile virtual keyboard |

Elements marked data-swipe-ignore never start a swipe.

Styling

Components are unstyled. Either import the starter stylesheet:

import 'svelte-base-drawer/drawer.css';

…or write your own CSS against the data attributes and the CSS custom properties driven by the engine (registered with inherits: false for performance):

| Variable | Meaning | | ----------------------------------------------- | ------------------------------------------------------------ | | --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-height / --drawer-frontmost-height | Measured heights, for nested stacking | | --nested-drawers | Number of open nested drawers | | --drawer-keyboard-inset | Software keyboard inset (requires VirtualKeyboardProvider) |

Key data attributes: data-swiping (during a drag), data-expanded (largest snap point), data-nested / data-nested-drawer-open (stacking), and bits-ui's data-starting-style / data-ending-style for enter/exit transitions.

A typical popup transform:

.my-popup {
	transform: translateY(
		calc(var(--drawer-snap-point-offset, 0px) + var(--drawer-swipe-movement-y, 0px))
	);
	transition: transform 450ms cubic-bezier(0.32, 0.72, 0, 1);
}
.my-popup[data-swiping] {
	transition-duration: 0ms;
}
.my-popup[data-ending-style] {
	transition-duration: calc(var(--drawer-swipe-strength, 1) * 400ms);
}
.my-popup[data-starting-style],
.my-popup[data-ending-style] {
	transform: translateY(100%);
}

See the demos (ports of the Base UI docs examples) in src/demos/ — snap points, nested drawers, virtual keyboard, indent effect, mobile navigation, swipe to open, action sheet — each with its full CSS.

Development

The repo is a SvelteKit app: the library lives in src/lib, the documentation/demo site in src/routes.

npm run dev       # docs site with all demos
npm run check     # svelte-check
npm run package   # build the package into dist/ + publint
npm run build     # static build of the docs site

Credits & license

MIT. Ported from Base UI (MIT © Material-UI SAS); the demos are adapted from the Base UI documentation. Built on bits-ui by Huntabyte.