Snap Points

Snap points let you define positions where the sheet should rest. Use fractions of the viewport height or fixed pixel values.

Basic snap points

Pass an array of numbers between 0 and 1 to define snap positions as fractions of the viewport height.

<BottomSheet.Root
  open={open}
  onOpenChange={setOpen}
  snapPoints={[0.5, 1]}
  activeSnapPoint={snap}
  onActiveSnapPointChange={setSnap}
>
  <BottomSheet.Portal>
    <BottomSheet.Overlay />
    <BottomSheet.Content>
      <BottomSheet.Handle />
      {/* Content */}
    </BottomSheet.Content>
  </BottomSheet.Portal>
</BottomSheet.Root>

Pixel values

You can mix fractions and pixel strings. Pixel values define the height from the bottom of the screen.

// Mix fractions and pixel values
snapPoints={[0, '200px', 0.5, 1]}

// 0     → closed (drag past this to dismiss)
// 200px → 200px from the bottom
// 0.5   → 50% of viewport height
// 1     → fully expanded

Sequential snapping

By default, a fast swipe can jump over intermediate snap points. Enable snapToSequentialPoint to force step-by-step navigation — the user must pass through each point in order.

<BottomSheet.Root
  snapPoints={[0, '200px', 0.5, 1]}
  snapToSequentialPoint  // only snap to adjacent points
  activeSnapPoint={snap}
  onActiveSnapPointChange={setSnap}
>

Controlled snap point

Use activeSnapPoint and onActiveSnapPointChange for full control. This lets you navigate programmatically — perfect for "expand" or "minimize" buttons.

const [snap, setSnap] = useState<SnapPoint | null>('200px');

// Navigate programmatically
<button onClick={() => setSnap(1)}>Expand</button>
<button onClick={() => setSnap('200px')}>Minimize</button>

Overlay with snap points

The fadeFromIndexprop controls when the overlay starts fading in. Set it to the index of the snap point where the overlay should become visible. By default it's the last snap point index.