Files
zeekay a572ed7c00 feat: add gui-docs app for gui.hanzo.ai
Migrated 93 MDX pages from old Tamagui-based site to @hanzo/docs system:
- 13 intro pages (installation, props, styles, themes, etc.)
- 22 core pages (configuration, styled, variants, animations, etc.)
- 48 component pages (button, dialog, select, toast, etc.)
- 14 guide pages (next-js, expo, vite, webpack, metro, etc.)

Zero tamagui references. Uses @hanzo/docs-base-ui + @hanzo/docs-mdx.
2026-03-29 16:47:38 -07:00

237 lines
7.1 KiB
Plaintext

---
title: Sheet
description: A bottom sheet that animates
name: sheet
component: Sheet
package: sheet
demoName: Sheet
---
- 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](/ui/z-index) above other content.
## Installation
Sheet is already installed in `@hanzo/gui`, or you can install it independently:
```bash
npm install @hanzogui/sheet
```
<Notice theme="blue">
For native apps, we recommend [setting up native
portals](/docs/components/portal#native-portal-setup-recommended) to preserve React
context inside Sheet content.
</Notice>
## Anatomy
```tsx
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.
<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. Hanzo GUI 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.`,
},
]}
/>
### Sheet.Overlay
Displays behind Frame. Extends [YStack](/docs/components/stacks).
### Sheet.Frame
Contains the content. Extends [YStack](/docs/components/stacks).
### 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](/docs/components/stacks).
### Sheet.ScrollView
Allows scrolling within Sheet. Extends
[ScrollView](/docs/components/scroll-view).
## 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`:
```bash
npm install react-native-gesture-handler
```
2. Add the setup import to your app entry point (before any Hanzo GUI imports):
```tsx
// 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:
```tsx
<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.