code/tamagui.dev/data/docs/components/sheet/2.0.0.mdx
<Highlights
features={[
Lightweight implementation with dragging support.,
Multiple snap points and a handle.,
Automatically adjusts to screen size.,
Accepts animations, themes, size props and more.,
]}
/>
Sheet is a bottom panel that slides up from the bottom of the screen, commonly used for mobile-friendly dialogs and action menus. It supports drag-to-dismiss, multiple snap points, and automatically stacks above other content.
Sheet is already installed in tamagui, or you can install it independently:
npm install @tamagui/sheet
import { Sheet } from 'tamagui' // or '@tamagui/sheet'
export default () => (
<Sheet>
<Sheet.Overlay />
<Sheet.Handle />
<Sheet.Frame></Sheet.Frame>
</Sheet>
)
Contains every component for the sheet.
<PropsTable
data={[
{
name: 'open',
type: 'boolean',
description: Set to use as controlled component.,
},
{
name: 'defaultOpen',
type: 'boolean',
description: Uncontrolled open state on mount.,
},
{
name: 'onOpenChange',
type: '(open: boolean) => void',
description: Called on change open, controlled or uncontrolled.,
},
{
name: 'position',
type: 'number',
description: Controlled position, set to an index of snapPoints.,
},
{
name: 'defaultPosition',
type: 'number',
description: Uncontrolled default position on mount.,
},
{
name: 'snapPoints',
type: 'number[]',
default: [80, 10],
description: 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.,
},
{
name: 'onPositionChange',
type: '(position: number) => void',
description: Called on change position, controlled or uncontrolled.,
},
{
name: 'dismissOnOverlayPress',
type: 'boolean',
default: 'true',
description: Controls tapping on the overlay to close, defaults to true.,
},
{
name: 'animationConfig',
type: 'Animated.SpringAnimationConfig',
default: 'true',
description: Customize the spring used, passed to react-native Animated.spring().,
},
{
name: 'native',
type: 'boolean | "ios"[]',
description: (iOS only) Render to a native sheet, must install native dependency first.,
},
{
name: 'disableDrag',
type: 'boolean',
description: Disables all touch events to drag the sheet.,
},
{
name: 'modal',
type: 'boolean',
description: Renders sheet into the root of your app instead of inline.,
},
{
name: 'dismissOnSnapToBottom',
type: 'boolean',
description: 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).,
},
{
name: 'disableRemoveScroll',
type: 'boolean',
default: 'false',
description: Disables the RemoveScroll behavior that prevents body scrolling while sheet is open. By default, RemoveScroll is enabled when the sheet is open and modal.,
},
{
name: 'forceRemoveScrollEnabled',
type: 'boolean',
default: 'false',
deprecated: true,
description: @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)., }, { name: 'portalProps', type: 'Object', description: YStack props that can be passed to the Portal that sheet uses when in modal mode., }, { name: 'moveOnKeyboardChange', type: 'boolean', default: 'false', description: 'Native-only flag that will make the sheet move up when the mobile keyboard opens so the focused input remains visible.', }, { name: 'preferAdaptParentOpenState', type: 'boolean', default: 'false', description: 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.`,
},
]}
/>
Displays behind Frame. Extends YStack.
Contains the content. Extends YStack.
Shows a handle above the frame by default. On tap, it will cycle between
snapPoints, but this can be overridden with onPress.
Extends XStack.
Allows scrolling within Sheet. Extends ScrollView.
For the best gesture experience on iOS and Android, Sheet supports optional integration with react-native-gesture-handler. This provides:
react-native-gesture-handler:npm install react-native-gesture-handler
// 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 }}></GestureHandlerRootView>
)
}
That's it! Sheet will automatically detect and use the native gesture handler when available.
When using scrollable content inside a Sheet, use Sheet.ScrollView for proper gesture coordination:
<Sheet>
<Sheet.Handle />
<Sheet.Frame>
<Sheet.ScrollView></Sheet.ScrollView>
</Sheet.Frame>
</Sheet>
This ensures:
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.
For Android you need to manually re-propagate any context when using modal.
This is because React Native doesn't support portals yet.
We've deprecated the native prop in favor of using Adapt.