FAQ

Frequently asked questions

Short answers, checked against the source. Longer detail lives in the docs links below.

Why use this instead of vaul?

vaul is the React drawer nearly everyone ships: 37 million downloads a week. scrollsheet drags via the browser's own scroll engine instead of simulating the gesture with pointer events, and renders a real native <dialog> instead of a portal, at 16.93 kB gzipped against vaul's Radix Dialog dependency tree. Full breakdown in the comparison table.

How big is it, really?

16.93 kB gzipped, 15.13 kB brotli, the bundled and minified size with React external, from bun run size against the current build. Zero runtime dependencies: react and react-dom are peer dependencies only, both >=18. See Install.

Does it work with Next.js App Router and React Server Components?

Yes. Every module that touches state or the DOM opens with "use client", including Sheet.Root, Content, Handle, Trigger, and both compat layers (vaul, sonner). Render <Sheet.Root> from a Server Component like any other client component; React draws the boundary for you.

Does it work with Tailwind?

Yes, Tailwind v4 out of the box: no plugin, no config. Utilities on className apply directly because the mechanics stylesheet only wins where it must (position, transform) and sits in zero-specificity :where() rules everywhere else. See Tailwind.

How accessible is it?

Modal focus containment comes from the platform's own showModal(), not a JS focus trap. With two or more detents, Sheet.Handle exposes role="slider" with aria-valuemin/-valuemax/-valuenow/-valuetext; Up/Down (or Left/Right on side sheets) move between stops, Home and End jump to the ends. See API.

Which browsers does it support?

Spring easing works from Chrome 113, Safari 17.2, and Firefox 112. The compositor-driven backdrop fade needs Chrome/Edge 115+ or Safari 26+; Firefox has it implemented but still behind a flag. Below Safari 15.4 there's no <dialog> at all, so the sheet falls back to a plain fixed-position modal: backdrop, tap-to-close, Escape, no detents or drag. Full matrix in Browser support.

Can I migrate from vaul without rewriting?

Mostly. import { Drawer } from 'scrollsheet' maps the same Drawer.* namespace onto Sheet.*: snapPoints, direction, modal={false}, shouldScaleBackground, and more all map to real features. Props that only existed to fight the page, like scroll-lock or portal containers, warn once in dev; Radix Dialog.Content-only props like onPointerDownOutside have no equivalent and are stripped. Full mapping in Migrate from vaul.

Can I migrate from Sonner without rewriting?

Mostly. import { toast, Toaster } from 'scrollsheet' is a drop-in for the same toast and Toaster, including .success()/.error()/.custom()/.promise() and toasterId-scoped toasters, running on the same per-toast DOM and positioning real Sonner uses. Your existing useSonner() calls and .sonner-toast CSS keep working unchanged; new code can call the same hook as useToasts() instead. v1 gaps: theme and richColors aren't implemented yet. Full mapping in Migrate from Sonner.

Does it support snap points?

They're called detents, Apple's term. Accepted forms: 'full', 'medium', 'content' (natural height), a fraction in (0, 1], or a pixel string like '320px'. See Detents.

Does it handle the iOS keyboard?

Yes, automatically. iOS resizes visualViewport, not the layout viewport, when the keyboard opens; scrollsheet listens and writes the inset to --scrollsheet-keyboard, and the panel overdraws about 120vh past its bottom edge so a stale frame never shows a gap. See Keyboard.

Does it work inside a Shadow DOM?

Rendering works, since the native dialog's top layer is document-level rather than shadow-scoped. The one thing you handle yourself: the auto-injected mechanics styles land in document.head, which a shadow root doesn't see, so call injectStylesInto(shadowRoot) before any Sheet.Content inside it opens. See Shadow DOM.

Is it maintained, and by whom?

Yes. scrollsheet is built by Ansuman Shah under the NoodleApps studio name, MIT-licensed, currently at v1.0.0-beta.1. Source and issues at github.com/ansumanshah/scrollsheet.