Sheet

A bottom sheet that animates

Snap Points: [85,50,25]

Features

  • Lightweight implementation with dragging support.

  • Multiple snap points and a handle.

  • Automatically adjusts to screen size.

  • Accepts animations, themes, size props and more.

Installation

Sheet is already installed in tamagui, or you can install it independently:

yarn add @tamagui/sheet

For native apps, we recommend setting up native portals to preserve React context inside Sheet content.

Anatomy

import { Sheet } from 'tamagui' // or '@tamagui/sheet'
export default () => (
<Sheet>
<Sheet.Overlay />
<Sheet.Handle />
<Sheet.Frame>{/* ...inner contents */}</Sheet.Frame>
</Sheet>
)

API Reference

Sheet

Contains every component for the sheet.

Props

  • open

    boolean

    Set to use as controlled component.

  • defaultOpen

    boolean

    Uncontrolled open state on mount.

  • onOpenChange

    (open: boolean) => void

    Called on change open, controlled or uncontrolled.

  • position

    number

    Controlled position, set to an index of snapPoints.

  • defaultPosition

    number

    Uncontrolled default position on mount.

  • snapPoints

    number[]

    Default: 

    [80, 10]

    Array of numbers, 0-100 that corresponds to % of the screen it should take up. Should go from most visible to least visible in order. Use "open" prop for fully closed.

  • onPositionChange

    (position: number) => void

    Called on change position, controlled or uncontrolled.

  • dismissOnOverlayPress

    boolean

    Default: 

    true

    Controls tapping on the overlay to close, defaults to true.

  • animationConfig

    Animated.SpringAnimationConfig

    Default: 

    true

    Customize the spring used, passed to react-native Animated.spring().

  • native

    boolean | "ios"[]

    (iOS only) Render to a native sheet, must install native dependency first.

  • disableDrag

    boolean

    Disables all touch events to drag the sheet.

  • modal

    boolean

    Renders sheet into the root of your app instead of inline.

  • dismissOnSnapToBottom

    boolean

    Adds a snap point to the end of your snap points set to "0", that when snapped to will set open to false (uncontrolled) and call onOpenChange with false (controlled).

  • disableRemoveScroll

    boolean

    Default: 

    false

    Disables the RemoveScroll behavior that prevents body scrolling while sheet is open. By default, RemoveScroll is enabled when the sheet is open and modal.

  • forceRemoveScrollEnabled

    boolean

    Default: 

    false
    deprecated

    @deprecated Use `disableRemoveScroll` instead. By default. Tamagui uses react-remove-scroll to prevent anything outside the sheet scrolling. This can cause some issues so you can override the behavior with this prop (either true or false).

  • portalProps

    Object

    YStack props that can be passed to the Portal that sheet uses when in modal mode.

  • moveOnKeyboardChange

    boolean

    Default: 

    false

    Native-only flag that will make the sheet move up when the mobile keyboard opens so the focused input remains visible.

  • preferAdaptParentOpenState

    boolean

    Default: 

    false

    By default Sheet will prefer the open prop over a parent component that is controlling it via Adapt. In general if you want to Adapt to a sheet, you'd leave the open prop undefined. If you'd like to have the parent override the prop you've set manually on Sheet, set this to true.

  • Sheet.Overlay

    Displays behind Frame. Extends YStack.

    Sheet.Frame

    Contains the content. Extends YStack.

    Sheet.Handle

    Shows a handle above the frame by default. On tap, it will cycle between snapPoints, but this can be overridden with onPress.

    Extends XStack.

    Sheet.ScrollView

    Allows scrolling within Sheet. Extends ScrollView.

    Native Gesture Handler Integration

    For the best gesture experience on iOS and Android, Sheet supports optional integration with react-native-gesture-handler. This provides:

    • Smooth scroll-to-drag handoffs - Seamlessly transition between scrolling content and dragging the sheet
    • No gesture conflicts - Sheet and ScrollView gestures coordinate properly
    • Native-quality feel - Matches the behavior of system sheets

    Setup

    1. Install react-native-gesture-handler:
    yarn add react-native-gesture-handler
    1. Add the setup import to your app entry point (before any Tamagui imports):
    // App.tsx or index.js
    import '@tamagui/native/setup-gesture-handler'
    import { GestureHandlerRootView } from 'react-native-gesture-handler'
    export default function App() {
    return (
    <GestureHandlerRootView style={{ flex: 1 }}>{/* Your app */}</GestureHandlerRootView>
    )
    }

    That’s it! Sheet will automatically detect and use the native gesture handler when available.

    Using Sheet.ScrollView

    When using scrollable content inside a Sheet, use Sheet.ScrollView for proper gesture coordination:

    <Sheet>
    <Sheet.Handle />
    <Sheet.Frame>
    <Sheet.ScrollView>{/* Scrollable content */}</Sheet.ScrollView>
    </Sheet.Frame>
    </Sheet>

    This ensures:

    • Scrolling up at the top of content works naturally
    • Dragging down when scroll is at top drags the sheet
    • Direction changes mid-gesture work smoothly

    Without Gesture Handler

    If you don’t set up react-native-gesture-handler, Sheet falls back to React Native’s built-in PanResponder. This works well for basic use cases but has some limitations on iOS where scroll and pan gestures can occasionally conflict.

    Notes

    For Android you need to manually re-propagate any context when using modal. This is because React Native doesn’t support portals yet.

    Native Support

    We’ve deprecated the native prop in favor of using Adapt.