@biem/ui

Drawer

A panel that slides in from an edge of the screen and that users swipe to close.

A drawer slides a panel in from an edge of the screen, where users read details or complete a short task without leaving the page. By default, it rises from the bottom edge, and while it is open, focus stays in the drawer and the page behind it doesn't scroll. Users close it with a swipe toward its edge, a close button, the Escape key or a press outside the drawer. On a touch screen, the swipe starts anywhere on the drawer. With a mouse, it starts on the swipe handle only, because a drag in the content selects text.

Usage

drawer-default.tsx
import { Button } from "@biem/ui/components/ui/button";
import {
	Drawer,
	DrawerClose,
	DrawerContent,
	DrawerDescription,
	DrawerFooter,
	DrawerHeader,
	DrawerTitle,
	DrawerTrigger,
} from "@biem/ui/components/ui/drawer";

export function DrawerDefault() {
	return (
		<Drawer>
			<DrawerTrigger render={<Button variant="outline"/>}>Review transfer</DrawerTrigger>
			<DrawerContent>
				<div className="mx-auto w-full max-w-sm">
					<DrawerHeader>
						<DrawerTitle>Transfer 4821</DrawerTitle>
						<DrawerDescription>
							The warehouse ships 12 cases to the store in Basel.
						</DrawerDescription>
					</DrawerHeader>
					<p className="p-4">
						The cases leave the warehouse on Monday. The store receives them on Tuesday between 6:00 and 8:00.
					</p>
					<DrawerFooter>
						<Button>Approve transfer</Button>
						<DrawerClose render={<Button variant="outline"/>}>Cancel</DrawerClose>
					</DrawerFooter>
				</div>
			</DrawerContent>
		</Drawer>
	);
}

Examples

Swipe Up

Some content belongs near the upper edge of a screen, such as filters that apply to the list beneath them. With swipeDirection set to "up", the drawer slides in from the top edge, and users close it with a swipe upward.

Swipe Down

On a phone, the lower edge lies within reach of the thumb, which makes it the natural place for a short task. This edge is the default, and swipeDirection set to "down" states it explicitly.

Swipe Left

Navigation between the areas of a product commonly opens from the left side of the screen. Set to "left", swipeDirection brings the drawer in from that edge, and a swipe to the left closes it again.

Swipe Right

Details that accompany the current page, such as the history of an order, usually open at the right edge. Through the value "right" of swipeDirection, the drawer enters from there, and users swipe it back to the right to close it.

With Swipe Handle

A drag with the mouse in the content of a drawer selects text instead of moving the drawer. Once showSwipeHandle is set, the drawer offers a handle that users drag with a mouse or a finger, to close the drawer or to move it to another snap point.

With Snap Points

Long content often deserves a first glance before users decide to read all of it. Through snapPoints, the drawer comes to rest at several heights, opens at the first of them, and moves between them as users swipe.

Default Snap Point

Where users need the full content from the start, defaultSnapPoint opens the drawer at another of its snap points instead of the first. Users still swipe it down to a smaller height or close it.

Controlled Snap Point

An application can move the drawer between its heights on its own, for example to expand it when a step inside it needs more room. For this, snapPoint and onSnapPointChange hold the current snap point in the application, while users keep swiping between the heights.

Sequential Snap Points

With three or more heights, a quick swipe can carry the drawer past the ones in between. Once snapToSequentialPoints is set, the distance of the drag alone decides the next snap point, and the speed of a swipe no longer skips one.

Nested

A task in a drawer can raise a related question that deserves room of its own. Opened from within the first, a second drawer stacks above it, and once users close it, they return to the first drawer as they left it.

Controlled

The application sometimes decides when the drawer opens or closes, for example to close it as soon as a change has been saved. Through open and onOpenChange it holds that state, and users keep every way to open and close the drawer.

Disabled Trigger

Details can depend on data that is still on its way, such as a report that has not been generated yet. Marked as disabled, the trigger no longer opens the drawer, while users still see that the details exist.

Disabled Close

A single close button can lose its purpose for a moment, for example while an entry is being saved. With disabled, that button ignores presses, yet a swipe, the Escape key and a press outside the drawer still close it.

API Reference

Drawer

Propopen
Typeboolean
Default–
DescriptionSets whether the drawer is open and makes it controlled. Update it in onOpenChange.
PropdefaultOpen
Typeboolean
Defaultfalse
DescriptionOpens the drawer at first render. The drawer then tracks its open state itself.
ProponOpenChange
Type(open: boolean, eventDetails: DrawerRootChangeEventDetails) => void
Default–
DescriptionRuns when users open or close the drawer. It receives the open state that follows.
ProponOpenChangeComplete
Type(open: boolean) => void
Default–
DescriptionRuns after the drawer has opened or closed and its animations have finished.
PropswipeDirection
Type"up" | "down" | "left" | "right"
Default"down"
DescriptionSets the direction of the swipe that closes the drawer, and with it the edge of the screen that the drawer slides in from. "down" places the drawer at the bottom edge, "up" at the top edge, "left" at the left edge and "right" at the right edge.
PropshowSwipeHandle
Typeboolean
Defaultfalse
DescriptionShows a handle on the side of the drawer that faces the page. Users drag it to close the drawer or to move it to another snap point. With a mouse, the handle is the only part of the drawer that starts a swipe.
PropsnapPoints
Type(number | string)[]
Default–
DescriptionSets the heights at which the drawer comes to rest. A number from 0 to 1 is a fraction of the viewport height, a number above 1 is a height in pixels, and a string is a height in px or rem, such as "16rem". Snap points only apply to the swipe directions "down" and "up".
PropsnapPoint
Typenumber | string | null
Default–
DescriptionSets the snap point at which the drawer rests and makes it controlled. Update it in onSnapPointChange.
PropdefaultSnapPoint
Typenumber | string | null
Default–
DescriptionSets the snap point at which the drawer opens. Without it, the drawer opens at the first entry of snapPoints. The drawer then tracks its snap point itself.
ProponSnapPointChange
Type(snapPoint: number | string | null, eventDetails: DrawerRootSnapPointChangeEventDetails) => void
Default–
DescriptionRuns when the snap point changes. It receives the snap point that follows, or null when users swipe the drawer closed. When the drawer closes, it receives the snap point at which the drawer opens next.
PropsnapToSequentialPoints
Typeboolean
Defaultfalse
DescriptionMakes the distance of the drag alone decide the next snap point. Without it, the speed of the swipe counts as well, so a fast swipe can skip snap points.
Propmodal
Typeboolean | "trap-focus"
Defaulttrue
DescriptionSets how the drawer limits the rest of the page while it is open. With true, focus stays in the drawer, the page doesn't scroll, and an overlay covers the page. With "trap-focus", focus stays in the drawer, but the page scrolls and has no overlay. With false, focus can move to the rest of the page, and the page scrolls and has no overlay.
PropdisablePointerDismissal
Typeboolean
Defaultfalse
DescriptionKeeps the drawer open when users press outside of it. A drawer with modal set to false then also stays open when focus moves outside of it.
ProptriggerId
Typestring | null
Default–
DescriptionSets the ID of the trigger that a controlled drawer is associated with. A drawer without open doesn't need it.
PropdefaultTriggerId
Typestring | null
Default–
DescriptionSets the ID of the trigger that the drawer is associated with when defaultOpen opens it at first render.
Prophandle
TypeDrawerHandle<Payload>
Default–
DescriptionConnects the drawer with triggers that are rendered outside of it. Create the handle with Drawer.createHandle() from @base-ui/react/drawer.
PropactionsRef
TypeRefObject<DrawerRootActions | null>
Default–
DescriptionReceives the functions close and unmount. close closes the drawer from code, and unmount removes it from the DOM after a closing animation that the code controls itself.
Propchildren
TypeReactNode | ((arg: { payload: Payload | undefined }) => ReactNode)
Default–
DescriptionHolds the parts of the drawer. A function receives the payload of the trigger that opened the drawer.

DrawerTrigger

Prophandle
TypeDrawerHandle<Payload>
Default–
DescriptionConnects the trigger with a drawer that it is rendered outside of. Pass the same handle to Drawer.
Proppayload
TypePayload
Default–
DescriptionPasses a value to the drawer when this trigger opens it. A function as children of Drawer receives it.
Propid
Typestring
Default–
DescriptionSets the ID of the trigger element. triggerId and defaultTriggerId of Drawer refer to it.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the trigger with another component.
PropnativeButton
Typeboolean
Defaulttrue
DescriptionDeclares whether the rendered element is a native button. Set it to false when render returns a different element.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from opening the drawer with this trigger.

DrawerPortal

PropkeepMounted
Typeboolean
Defaultfalse
DescriptionKeeps the portal in the DOM while the drawer is closed.
Propcontainer
TypeHTMLElement | ShadowRoot | RefObject<HTMLElement | ShadowRoot | null> | null
Default–
DescriptionSets the element that the portal is rendered into. Without it, the portal is appended to the body.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the portal with another component.

DrawerOverlay

PropforceRender
Typeboolean
Defaultfalse
DescriptionRenders the overlay even when the drawer is nested in another drawer.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the overlay with another component.

DrawerContent

PropinitialFocus
Typeboolean | RefObject<HTMLElement | null> | ((openType: InteractionType) => boolean | HTMLElement | null | void)
Default–
DescriptionDetermines the element that receives focus when the drawer opens. Without it, focus moves to the drawer itself and not to an element inside it.
PropfinalFocus
Typeboolean | RefObject<HTMLElement | null> | ((closeType: InteractionType) => boolean | HTMLElement | null | void)
Default–
DescriptionDetermines the element that receives focus when the drawer closes. Without it, focus returns to the trigger or to the element that had focus before.
Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the content with another component.

DrawerSwipeHandle

DrawerSwipeHandle shows the bar that users drag to close the drawer or to move it to another snap point. DrawerContent renders it when showSwipeHandle is set on Drawer. It renders a div and has no props of its own.

DrawerHeader

DrawerHeader groups the title and the description. It renders a div and has no props of its own.

DrawerTitle

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the title with another component.

DrawerDescription

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the description with another component.

DrawerFooter

DrawerFooter stacks the actions at the end of the drawer. It renders a div and has no props of its own.

DrawerClose

Proprender
TypeReactElement | render function
Default–
DescriptionReplaces the native element or composes the close button with another component.
PropnativeButton
Typeboolean
Defaulttrue
DescriptionDeclares whether the rendered element is a native button. Set it to false when render returns a different element.
Propdisabled
Typeboolean
Defaultfalse
DescriptionPrevents users from closing the drawer with this button.