Sheet
A bottom sheet that animates
- 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.
Installation
Sheet is already installed in @hanzo/gui, or you can install it independently:
npm install @hanzogui/sheetFor native apps, we recommend setting up native portals to preserve React context inside Sheet content.
Anatomy
import { Sheet } from '@hanzo/gui' // or '@hanzogui/sheet'
export default () => (
<Sheet>
<Sheet.Overlay />
<Sheet.Handle />
<Sheet.Frame>{/* ...inner contents */}</Sheet.Frame>
</Sheet>
)API Reference
Sheet
Contains every component for the sheet.
| Prop | Type | Default | Required |
|---|---|---|---|
| open | boolean | - | - |
| defaultOpen | boolean | - | - |
| onOpenChange | (open: boolean) => void | - | - |
| position | number | - | - |
| defaultPosition | number | - | - |
| snapPoints | number[] | [80, 10] | - |
| onPositionChange | (position: number) => void | - | - |
| dismissOnOverlayPress | boolean | true | - |
| animationConfig | Animated.SpringAnimationConfig | true | - |
| native | boolean | "ios"[] | - | - |
| disableDrag | boolean | - | - |
| modal | boolean | - | - |
| dismissOnSnapToBottom | boolean | - | - |
| disableRemoveScroll | boolean | false | - |
| forceRemoveScrollEnabled | boolean | false | - |
| portalProps | Object | - | - |
| moveOnKeyboardChange | boolean | false | - |
| preferAdaptParentOpenState | boolean | false | - |
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
- Install
react-native-gesture-handler:
npm install react-native-gesture-handler- Add the setup import to your app entry point (before any Hanzo GUI imports):
// App.tsx or index.js
import '@hanzogui/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.
Last updated on