Accessible, Delightful, and Performant


Built on top of react-spring and react-use-gesture, following best practices for minimal rerenders and only animating CSS properties that can be done on the GPU when possible.


Can be used like a blocking dialog that require the user to make a choice before it can be closed, or like floating bottom panel. It automatically adapts to the dimensions of the content you put in it.

CSS Variables

By using CSS Custom Properties you're not limited by what is spring animated by default. You can change which elements animations are applied to without writing any JS.

Easy to dismiss

It should be just as intuitive to close the bottom sheet no matter if you're using touch, keyboard navigation, a screen reader or a mouse cursor.

This example is setup to use a single snap point, set to the content height. The sheet adjusts itself accordingly if the content changes.

Open example 👀

Snap points & overflow

The snap points api lets you control exactly what positions the sheet can be in. If the user drag the sheet out of bounds you'll get a rubber band effect, and it gently slides into position on release. You can even flick it from top to bottom with some speed, if that's your jam.

By default the sheet will try to use enough height to avoid a scrolling overflow.

And finally, it shows how the sheet behaves when you don't provide the onDismiss callback, note how you can't close it.

Open example 👀

Sticky Header & Footer

Can be really tricky to implement in a performant way. Luckily with this component you don't have to worry about that.

By adding a header the touch hit target is much larger, making it more pleasant to use.

For those big thicc phones they'll be happy to find that you can swipe on the sticky footer to adust the height, making one-handed usage a bit easier.

On top of all that see how it remembers the last snap position it had when closing, and restore it when reopened.

One more thing, the opening transition is interruptible, you can start dragging it right away.

Open example 👀

Non-blocking mode

Examples so far have all been with blocking=true, which is the default state. It's comparable to a blocking modal dialog, you can't interract with the rest of the page until the dialog closes.

This mode can be turned off and changes the look and feel of the sheet to fit scenarios where it's used as you would a draggable sidebar.

Or as an search overlay over a map perhaps.

Open example 👀