Drawer

import { Drawer, DrawerContent, DrawerHandle, DrawerTrigger } from '@hanzo/ui'

Default

A sheet that slides up from the bottom edge, with its own handle.

export function Default() {
return (
<Drawer>
<DrawerTrigger asChild>
<Button variant="outline">Open</Button>
</DrawerTrigger>
<DrawerContent>
<YStack p="$5" gap="$2">
<Text fontWeight="600">Move to trash?</Text>
<Paragraph color="$color11">
The file stays recoverable for thirty days.
</Paragraph>
</YStack>
</DrawerContent>
</Drawer>
)
}

Snap points

The sheet rests at a third of the viewport, then the top.

export function SnapPoints() {
return (
<Drawer snapPoints={[0.33, 1]}>
<DrawerTrigger asChild>
<Button variant="outline">Open at a third</Button>
</DrawerTrigger>
<DrawerContent>
<YStack p="$5" gap="$2">
<Text fontWeight="600">Nearby</Text>
<Paragraph color="$color11">
Drag the handle up for the full list.
</Paragraph>
</YStack>
</DrawerContent>
</Drawer>
)
}

Controlled

The app owns `open`, so a button inside can close it.

export function Controlled() {
const [open, setOpen] = useState(false)
return (
<Drawer open={open} onOpenChange={setOpen} dragHandleOnly>
<DrawerTrigger asChild>
<Button variant="outline">{open ? "Opened" : "Open"}</Button>
</DrawerTrigger>
<DrawerContent defaultHandle={false}>
<DrawerHandle />
<YStack p="$5" gap="$3">
<Paragraph>
Only the handle drags, so this content can scroll.
</Paragraph>
<Button onPress={() => setOpen(false)}>Done</Button>
</YStack>
</DrawerContent>
</Drawer>
)
}

Types

export type SnapPoint = number | string
export type DrawerProps = React.PropsWithChildren<{
open?: boolean
onOpenChange?: (open: boolean) => void
/** Blocks the page behind it and dims it. */
modal?: boolean
snapPoints?: SnapPoint[]
/** `null` is "not decided yet", which a store holding this can be. */
activeSnapPoint?: SnapPoint | null
setActiveSnapPoint?: (point: SnapPoint) => void
/**
* The sheet was dismissed by a GESTURE — dragged or flicked below its
* shortest point — as opposed to closed by the app. Worth telling apart: one
* is the person saying no, the other is the flow moving on.
*/
handleCloseGesture?: () => void
/** Only the handle starts a drag — so the content can scroll. */
dragHandleOnly?: boolean
/** A fast flick goes to the far end rather than the next point along. */
fastDragSkipsToEnd?: boolean
/** A click on the handle, as opposed to a drag. */
handleHandleClicked?: () => void
/** Widen the handle's grab area past its drawn size. */
extendHandleDragRegion?: boolean
}>
export type DrawerContentProps = React.ComponentProps<typeof Box> & {
/** The sheet draws its own handle unless the caller draws one. */
defaultHandle?: boolean
/**
* Fires as the sheet takes focus. `preventDefault()` leaves focus where it
* was — which is what a sheet that opens beside a form the person is still
* typing in wants.
*/
onOpenAutoFocus?: (e: Event) => void
}

Exports

DrawerDrawerContentDrawerHandleDrawerTriggertype DrawerContentPropstype DrawerPropstype SnapPoint