tetra-ui Logotetra ui

Bottom Sheet

An interactive bottom sheet with snap points, gestures, scroll coordination, and keyboard support.

Bottom Sheet wraps @gorhom/bottom-sheet with a compound component API similar to Native Sheet. It is the recommended sheet component for new projects—whether you need draggable snap points, scrollable content, keyboard-aware forms, or a simple modal sheet.

bottom-sheet

Installation

npx shadcn@latest add @tetra-ui/bottom-sheet

Usage

import { Button, ButtonText } from "@/components/ui/button";
import {
  BottomSheet,
  BottomSheetBody,
  BottomSheetClose,
  BottomSheetContent,
  BottomSheetFooter,
  BottomSheetHeader,
  BottomSheetOverlay,
  BottomSheetPortal,
  BottomSheetTitle,
  BottomSheetTrigger,
} from "@/components/ui/bottom-sheet";
<BottomSheet>
  <BottomSheetTrigger asChild>
    <Button>
      <ButtonText>Open</ButtonText>
    </Button>
  </BottomSheetTrigger>
  <BottomSheetPortal>
    <BottomSheetOverlay />
    <BottomSheetContent>
      <BottomSheetHeader>
        <BottomSheetTitle>Bottom Sheet Title</BottomSheetTitle>
      </BottomSheetHeader>
      <BottomSheetBody>
        <Text className="text-foreground">Bottom Sheet Body</Text>
      </BottomSheetBody>
      <BottomSheetFooter>
        <BottomSheetClose asChild>
          <Button>
            <ButtonText>Close</ButtonText>
          </Button>
        </BottomSheetClose>
      </BottomSheetFooter>
    </BottomSheetContent>
  </BottomSheetPortal>
</BottomSheet>

Snap points

Pass fractional values (0.440%), pixel numbers, or percentage strings to BottomSheetContent:

<BottomSheetContent snapPoints={[0.35, 0.65, 1]} defaultSnapIndex={1}>
  {/* ... */}
</BottomSheetContent>

Scrollable content

Use BottomSheetScrollView for long lists so scrolling does not conflict with sheet drag gestures. Place BottomSheetHeader as a sibling above the scroll view — it stays pinned at the top while content scrolls beneath it (same pattern as BottomSheetFooter):

<BottomSheetContent snapPoints={[0.5, 0.9]}>
  <BottomSheetHeader>
    <BottomSheetTitle>List</BottomSheetTitle>
  </BottomSheetHeader>
  <BottomSheetScrollView>
    {/* scrollable items */}
  </BottomSheetScrollView>
</BottomSheetContent>

Keyboard

With snap points configured, call useBottomSheetInputHandlers() inside the sheet and pass onFocus / onBlur to inputs. The sheet expands to the highest snap while focused:

function SheetForm() {
  const { onFocus, onBlur } = useBottomSheetInputHandlers();

  return (
    <TextInput onFocus={onFocus} onBlur={onBlur} placeholder="Message" />
  );
}

Bottom Sheet vs Native Sheet

FeatureBottom SheetNative Sheet
Foundation@gorhom/bottom-sheetReact Native Modal
Snap pointsYesNo
Drag to resize / dismissYesNo
Scroll coordinationBottomSheetScrollViewManual
Keyboard awarenessYesNo
Overlay opacity vs expansionAnimated with snap indexFade with open state
Sticky footerBottomSheetFooterNativeSheetFooter
Best forInteractive sheets, forms, listsSimple dialogs, selects

Changelog

2026-05-25 Initial release

  • Compound API: BottomSheet, BottomSheetPortal, BottomSheetOverlay, BottomSheetContent, and layout primitives
  • Snap points, pan-down-to-close, dynamic sizing
  • BottomSheetScrollView, sticky BottomSheetFooter, useBottomSheetInputHandlers

On this page