Back to elements
ElementOverlayFree

Bottom Sheet React component

A mobile bottom sheet that slides up over a dimmed backdrop, rests at snap points you drag between from its handle, closes on a downward flick, and keeps its own content scrollable.

When to use the Bottom Sheet component

Use Bottom Sheet on phones for secondary tasks that should keep the page in view: filters, a list of results over a map, share targets, quick settings. People can pull it up for more room or flick it away with one thumb.

On larger screens a Drawer from the side or a Popover usually fits better; many apps render a Bottom Sheet on mobile and a Drawer on desktop.

Installation

Add the Bottom Sheet component to your project with the shadcn CLI. It lands in components/bottom-sheet.tsx as plain React + Tailwind CSS source you own and can edit.

Install
Copied!
npx shadcn@latest add https://reactframe.com/r/bottom-sheet.json

Or copy the source by hand and install its dependencies:

Install
Copied!
npm install motion clsx tailwind-merge

Props

<BottomSheet /> accepts 14 props, all optional.

  • open
    boolean
  • defaultOpen
    boolean
    Default: false
  • onOpenChange
    (open: boolean) => void
  • snapPoints

    Heights it rests at, as fractions of the screen (or container), smallest first.

    number[]
    Default: [0.45, 0.92]
  • defaultSnap

    Which snap point it opens to (index into snapPoints).

    number
    Default: 0
  • onSnapChange
    (index: number) => void
  • title
    string
  • description
    string
  • children
    React.ReactNode
  • triggerLabel

    A button that opens the sheet. Leave out and control it with open / onOpenChange.

    string
  • dismissible

    Drag down, tap the backdrop or press Escape to close.

    boolean
    Default: true
  • contained

    Place the sheet inside the nearest positioned ancestor instead of over the whole page.

    boolean
    Default: false
Show all 14 props
  • theme
    "dark" | "light"
    Default: "dark"
  • className
    string

FAQ

How do snap points work?
They're heights as fractions of the screen (or container with contained). The sheet opens at defaultSnap and settles on whichever point is closest to where a drag or flick carries it.
Why can't I drag it from the content?
On purpose: dragging starts only from the handle and header, so a long list inside scrolls normally. Tapping the handle also steps between snap points.
Can it stay open instead of closing when dragged down?
Set dismissible={false}. It then settles on the lowest snap point and ignores the backdrop and Escape.

Related components

Lightbox
Free
Cookie Consent Banner
Free
Product Tour
Free
Drawer
Free
Popover
Free
Modal
Free