Drawer
A panel that slides in from the edge of the screen.
View as MarkdownUsage guidelines
- Drawer extends Dialog: It adds gesture support, snap points, and indent effects. If you don’t need these, use Dialog instead. A panel that slides in from the edge of the screen and doesn’t need gesture support is a positioned Dialog.
Anatomy
Import the component and assemble its parts:
Drawer supports swipe gestures to dismiss. Set swipeDirection to control which direction dismisses the drawer. <Drawer.Content> allows text selection of its children without swipe interference when using a mouse pointer. Add data-base-ui-swipe-ignore to a descendant when you need to opt that element out of swipe dismissal for all input types.
Examples
State
By default, Drawer is an uncontrolled component that manages its own state.
Use open and onOpenChange props if you need to access or control the state of the drawer.
Position
Positioning is handled by your styles. swipeDirection defaults to "down" for bottom sheets. Use "up", "left", or "right" for other drawer positions.
Nested drawers
Use the [data-nested-drawer-open] selector and the --nested-drawers CSS variable to style drawers when a nested drawer is open.
This demo stacks nested drawers using a constant peek so the frontmost drawer stays anchored to the bottom while the ones behind it are scaled down and lifted. It also uses the --drawer-height and --drawer-frontmost-height CSS variables to handle varying drawer heights.
Snap points
Use snapPoints to snap a bottom sheet drawer to preset heights. Numbers between 0 and 1 represent fractions of the viewport height, and numbers greater than 1 are treated as pixel values. String values support px and rem units (for example, '148px' or '30rem').
Apply the snap point offset in your styles when using vertical drawers:
By default, the drawer can skip snap points when swiping quickly. Specify the snapToSequentialPoints prop to disable velocity-based skipping so the snap target is determined by drag distance (you can still drag past multiple points).
Indent effect
Scale the background down when any drawer opens by wrapping your app in <Drawer.Provider> and use <Drawer.IndentBackground> + <Drawer.Indent> at the top of your tree. Any <Drawer.Root> within the provider notifies it when it mounts, which activates the indent parts (they receive [data-active] state attributes).
Non-modal
Set modal={false} to opt out of focus trapping and disablePointerDismissal to keep the drawer open on outside clicks.
Mobile navigation
You can build a full-screen mobile navigation sheet using Drawer parts, including a flick-to-dismiss from the top gesture.
Swipe to open
Place <Drawer.SwipeArea> along the edge of the viewport to enable swipe-to-open gestures.
Swipe from the right edge to open the drawer.
Action sheet with separate destructive action
This demo builds an action sheet with a grouped list of actions plus a separate destructive action button.
Detached triggers
A drawer can be controlled by a trigger located either inside or outside the <Drawer.Root> component. For simple, one-off interactions, place the <Drawer.Trigger> inside <Drawer.Root>.
However, if defining the drawer’s content next to its trigger is not practical, you can use a detached trigger. This involves placing the <Drawer.Trigger> outside of <Drawer.Root> and linking them with a handle created by the Drawer.createHandle() function.
The drawer can render different content depending on which trigger opened it. This is achieved by passing a payload to the <Drawer.Trigger> and using the function-as-a-child pattern in <Drawer.Root>.
Stacking and animations
Use CSS transitions or animations to animate drawer opening, closing, swipe interactions, and nested stacking. The data-starting-style attribute is applied when a drawer starts to open, and data-ending-style is applied when it starts to close.
The --nested-drawers CSS variable can be used to determine stack depth. The frontmost drawer has index 0.
When stacked drawers have varying heights, use the --drawer-height and --drawer-frontmost-height variables to keep collapsed drawers aligned with the frontmost one.
The data-nested-drawer-open attribute marks drawers behind the frontmost drawer. Use it with data-nested-drawer-swiping to dim or hide parent drawer content while keeping it visible during nested swipe interactions.
The --drawer-swipe-movement-x, --drawer-swipe-movement-y, and --drawer-snap-point-offset CSS variables can be used to create smooth drag and snap offsets:
The data-swipe-direction attribute can be used with data-ending-style to animate directional dismissal:
Use --drawer-swipe-progress to fade the backdrop as the drawer is swiped, and --drawer-swipe-strength to scale release transition durations based on swipe velocity.
API reference
Provider
Provides a shared context for coordinating global Drawer UI, such as indent/background effects based on whether any Drawer is open. Doesn’t render its own HTML element.
childrenReact.ReactNode—
- Name
- Type
Drawer.Provider.StateHide
IndentBackground
An element placed before <Drawer.Indent> to render a background layer that can be styled based on whether any drawer is open.
Renders a <div> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.IndentBackground.PropsHide
Re-Export of IndentBackground props as DrawerIndentBackgroundProps
Drawer.IndentBackground.StateHide
Indent
A wrapper element intended to contain your app’s main UI.
Applies data-active when any drawer within the nearest <Drawer.Provider> is open.
Renders a <div> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Indent.StateHide
Root
Groups all parts of the drawer. Doesn’t render its own HTML element.
defaultOpenbooleanfalse
- Name
- Description
Whether the drawer is initially open.
To render a controlled drawer, use the
openprop instead.- Type
- Default
false
openboolean—
- Name
- Description
Whether the drawer is currently open.
- Type
onOpenChangefunction—
- Name
- Description
Event handler called when the drawer is opened or closed.
- Type
snapPointsDrawerSnapPoint[]—
- Name
- Description
Snap points used to position the drawer. Use numbers between 0 and 1 to represent fractions of the viewport height, numbers greater than 1 as pixel values, or strings in
px/remunits (for example,'148px'or'30rem').- Type
defaultSnapPointDrawerSnapPoint | null—
- Name
- Description
The initial snap point value when uncontrolled.
- Type
snapPointDrawerSnapPoint | null—
- Name
- Description
The currently active snap point. Use with
onSnapPointChangeto control the snap point.- Type
onSnapPointChangefunction—
- Description
Callback fired when the snap point changes.
- Type
actionsRefReact.RefObject<Drawer.Root.Actions | null>—
- Name
- Description
A ref to imperative actions.
unmount: When specified, the drawer will not be unmounted when closed. Instead, theunmountfunction must be called to unmount the drawer manually. Useful when the drawer’s animation is controlled by an external library.close: Closes the drawer imperatively when called.
- Type
defaultTriggerIdstring | null—
- Name
- Description
ID of the trigger that the drawer is associated with. This is useful in conjunction with the
defaultOpenprop to create an initially open drawer.- Type
disablePointerDismissalbooleanfalse
- Description
Determines whether the drawer should close on outside clicks.
- Type
- Default
false
handleDrawer.Handle<Payload>—
- Name
- Description
A handle to associate the drawer with a trigger. If specified, allows detached triggers to control the drawer’s open state. Can be created with the Drawer.createHandle() method.
- Type
modalboolean | 'trap-focus'true
- Name
- Description
Determines if the drawer enters a modal state when open.
true: user interaction is limited to just the drawer: focus is trapped, document page scroll is locked, and pointer interactions on outside elements are disabled.false: user interaction with the rest of the document is allowed.'trap-focus': focus is trapped inside the drawer, but document page scroll is not locked and pointer interactions outside of it remain enabled.
- Type
- Default
true
onOpenChangeCompletefunction—
- Description
Event handler called after any animations complete when the drawer is opened or closed.
- Type
snapToSequentialPointsbooleanfalse
- Description
Disables velocity-based snap skipping so drag distance determines the next snap point.
- Type
- Default
false
swipeDirectionDrawerSwipeDirection'down'
- Name
- Description
The swipe direction used to dismiss the drawer.
- Type
- Default
'down'
triggerIdstring | null—
- Name
- Description
ID of the trigger that the drawer is associated with. This is useful in conjunction with the
openprop to create a controlled drawer. There’s no need to specify this prop when the drawer is uncontrolled (that is, when theopenprop is not set).- Type
children| React.ReactNode
| PayloadChildRenderFunction<Payload>—
| PayloadChildRenderFunction<Payload>
- Name
- Description
The content of the drawer.
- Type
Drawer.Root.StateHide
Drawer.Root.ActionsHide
Drawer.Root.ChangeEventReasonHide
Drawer.Root.ChangeEventDetailsHide
Drawer.Root.SnapPointHide
Drawer.Root.SnapPointChangeEventDetailsHide
Drawer.Root.SnapPointChangeEventReasonHide
Trigger
A button that opens the drawer.
Renders a <button> element.
handleDrawerHandle<Payload>—
- Name
- Description
A handle to associate the trigger with a drawer. Can be created with the Drawer.createHandle() method.
- Type
nativeButtonbooleantrue
- Name
- Description
Whether the component renders a native
<button>element when replacing it via therenderprop. Set tofalseif the rendered element is not a button (for example,<div>).- Type
- Default
true
payloadPayload—
- Name
- Description
A payload to pass to the drawer when it is opened.
- Type
idstring—
- Name
- Description
ID of the trigger. In addition to being forwarded to the rendered element, it is also used to specify the active trigger for drawers in controlled mode (with the Drawer.Root
triggerIdprop).- Type
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Trigger.StateHide
SwipeArea
An invisible area that listens for swipe gestures to open the drawer.
Renders a <div> element.
swipeDirectionDrawerSwipeDirection—
- Name
- Description
The swipe direction that opens the drawer. Defaults to the opposite of
Drawer.RootswipeDirection.- Type
disabledbooleanfalse
- Name
- Description
Whether the swipe area is disabled.
- Type
- Default
false
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-open
Present when the drawer is open.
data-closed
Present when the drawer is closed.
data-disabled
Present when the swipe area is disabled.
data-swipe-direction
Indicates the swipe direction.
data-swiping
Present when the drawer is being swiped.
| Attribute | Description | |
|---|---|---|
data-open | Present when the drawer is open. | |
data-closed | Present when the drawer is closed. | |
data-disabled | Present when the swipe area is disabled. | |
data-swipe-direction | Indicates the swipe direction. | |
data-swiping | Present when the drawer is being swiped. | |
Drawer.SwipeArea.StateHide
Portal
A portal element that moves the popup to a different part of the DOM.
By default, the portal element is appended to <body>.
Renders a <div> element.
containerUnion—
- Name
- Description
A parent element to render the portal element into.
- Type
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
keepMountedbooleanfalse
- Name
- Description
Whether to keep the portal mounted in the DOM while the popup is hidden.
- Type
- Default
false
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Portal.StateHide
Backdrop
An overlay displayed beneath the popup.
Renders a <div> element.
forceRenderbooleanfalse
- Name
- Description
Whether the backdrop is forced to render even when nested.
- Type
- Default
false
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-open
Present when the drawer is open.
data-closed
Present when the drawer is closed.
data-starting-style
Present when the drawer is animating in.
data-ending-style
Present when the drawer is animating out.
| Attribute | Description | |
|---|---|---|
data-open | Present when the drawer is open. | |
data-closed | Present when the drawer is closed. | |
data-starting-style | Present when the drawer is animating in. | |
data-ending-style | Present when the drawer is animating out. | |
--drawer-swipe-progress
The swipe progress of the drawer gesture.
| CSS Variable | Description | |
|---|---|---|
--drawer-swipe-progress | The swipe progress of the drawer gesture. | |
Drawer.Backdrop.StateHide
Viewport
A positioning container for the drawer popup that can be made scrollable.
Renders a <div> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-open
Present when the drawer is open.
data-closed
Present when the drawer is closed.
data-nested
Present when the drawer is nested within another drawer.
data-starting-style
Present when the drawer is animating in.
data-ending-style
Present when the drawer is animating out.
| Attribute | Description | |
|---|---|---|
data-open | Present when the drawer is open. | |
data-closed | Present when the drawer is closed. | |
data-nested | Present when the drawer is nested within another drawer. | |
data-starting-style | Present when the drawer is animating in. | |
data-ending-style | Present when the drawer is animating out. | |
Drawer.Viewport.StateHide
Popup
A container for the drawer contents.
Renders a <div> element.
initialFocusUnion—
- Name
- Description
Determines the element to focus when the drawer is opened.
false: Do not move focus.true: Move focus based on the default behavior (first tabbable element or popup).RefObject: Move focus to the ref element.function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior, orfalse/undefinedto do nothing.
- Type
finalFocusUnion—
- Name
- Description
Determines the element to focus when the drawer is closed.
false: Do not move focus.true: Move focus based on the default behavior (trigger or previously focused element).RefObject: Move focus to the ref element.function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior, orfalse/undefinedto do nothing.
- Type
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
data-open
Present when the drawer is open.
data-closed
Present when the drawer is closed.
data-expanded
Present when the drawer is at the expanded (full-height) snap point.
data-nested-drawer-open
Present when a nested drawer is open.
data-nested-drawer-swiping
Present when a nested drawer is being swiped.
data-swipe-direction
Indicates the swipe direction.
data-swipe-dismiss
Present when the drawer is dismissed by swiping.
data-swiping
Present when the drawer is being swiped.
data-starting-style
Present when the drawer is animating in.
data-ending-style
Present when the drawer is animating out.
| Attribute | Description | |
|---|---|---|
data-open | Present when the drawer is open. | |
data-closed | Present when the drawer is closed. | |
data-expanded | Present when the drawer is at the expanded (full-height) snap point. | |
data-nested-drawer-open | Present when a nested drawer is open. | |
data-nested-drawer-swiping | Present when a nested drawer is being swiped. | |
data-swipe-direction | Indicates the swipe direction. | |
data-swipe-dismiss | Present when the drawer is dismissed by swiping. | |
data-swiping | Present when the drawer is being swiped. | |
data-starting-style | Present when the drawer is animating in. | |
data-ending-style | Present when the drawer is animating out. | |
--drawer-frontmost-height
The height of the frontmost open drawer in the current nested drawer stack.
--drawer-height
The height of the drawer popup.
--drawer-snap-point-offset
The snap point offset used for translating the drawer.
--drawer-swipe-movement-x
The swipe movement on the X axis.
--drawer-swipe-movement-y
The swipe movement on the Y axis.
--drawer-swipe-strength
A scalar (0.1–1) used to scale the swipe release transition duration in CSS.
--nested-drawers
The number of nested drawers that are currently open.
| CSS Variable | Description | |
|---|---|---|
--drawer-frontmost-height | The height of the frontmost open drawer in the current nested drawer stack. | |
--drawer-height | The height of the drawer popup. | |
--drawer-snap-point-offset | The snap point offset used for translating the drawer. | |
--drawer-swipe-movement-x | The swipe movement on the X axis. | |
--drawer-swipe-movement-y | The swipe movement on the Y axis. | |
--drawer-swipe-strength | A scalar (0.1–1) used to scale the swipe release transition duration in CSS. | |
--nested-drawers | The number of nested drawers that are currently open. | |
Drawer.Popup.StateHide
Content
A container for the drawer contents.
Renders a <div> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Content.StateHide
Title
A heading that labels the drawer.
Renders an <h2> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Title.StateHide
Description
A paragraph with additional information about the drawer.
Renders a <p> element.
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Description.PropsHide
Re-Export of Description props as DrawerDescriptionProps
Drawer.Description.StateHide
Close
A button that closes the drawer.
Renders a <button> element.
nativeButtonbooleantrue
- Name
- Description
Whether the component renders a native
<button>element when replacing it via therenderprop. Set tofalseif the rendered element is not a button (for example,<div>).- Type
- Default
true
classNamestring | function—
- Name
- Description
CSS class applied to the element, or a function that returns a class based on the component’s state.
- Type
styleReact.CSSProperties | function—
- Name
- Description
Style applied to the element, or a function that returns a style object based on the component’s state.
- Type
renderReactElement | function—
- Name
- Description
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a
ReactElementor a function that returns the element to render.- Type
Drawer.Close.StateHide
createHandle
Creates a new handle to connect a Dialog.Root with detached Dialog.Trigger components.
Return value
Handle
A handle to control a Dialog imperatively and to associate detached triggers with it.
Constructor parameters
storeDialogStore<Payload>—
- Name
- Type
Properties
isOpenreadonly
- Name
- Description
Indicates whether the dialog is currently open.
- Type
- Modifiers
readonly
Methods
open(triggerId)
- Name
- Description
Opens the dialog and associates it with the trigger with the given id. The trigger, if provided, must be a Dialog.Trigger component with this handle passed as a prop.
This method should only be called in an event handler or an effect (not during rendering).
- Parameters
triggerId—ID of the trigger to associate with the dialog. If null, the dialog will open without a trigger association.
- Returns
openWithPayload(payload)
- Name
- Description
Opens the dialog and sets the payload. Does not associate the dialog with any trigger.
- Parameters
payload—Payload to set when opening the dialog.
- Returns
close()
- Name
- Description
Closes the dialog.
- Returns