Skip to content
v2.5.0
English
Русский
Documentation

Drawer

Drawer is a compound component for edge-mounted overlays that preserve more page context than a centered modal.

Root Props

PropTypeDefault
defaultOpenbooleanfalse
Controls whether the drawer is default open.
openboolean—
Controls whether the drawer is open. When provided, the component becomes controlled.
onChangeOpen(value: boolean) => void—
Callback fired when the drawer's open state changes. Receives the new state as a boolean.
positionDrawerPosition'end'
Defines from which side of the screen the drawer appears. start and end follow the writing direction, like CSS logical properties: in right-to-left text end is the left side.
childrenReactNode—
The content to display inside the drawer. Typically, includes navigation, settings, or forms.

Child Parts

DrawerTrigger

Open action for the drawer. Sets aria-haspopup="dialog" and aria-expanded.

PropTypeDefault
asChildboolean—
If true, renders the trigger as a child element using Slot. This enables custom wrappers (e.g., <a>, <div>) to inherit drawer-opening behavior.
refRef<HTMLButtonElement>—
Ref forwarded to the native button or slotted element. Useful for focus management or integrations.

Also accepts all <button> attributes.

DrawerContent

The native modal <dialog>, positioned by the root position.

PropTypeDefault
refRef<HTMLDialogElement>—
Ref forwarded to the native <dialog> element. Useful for measuring, focusing, or animation hooks.
shadowedboolean—
Adds a shadow to the drawer panel for depth and separation.
blurredbooleantrue
Blurs the page behind the drawer.
overlaybooleantrue
Dims the page behind the drawer. When false, the page stays visible and the drawer stays modal.
closedByModalDialogClosedBy'any'
Which user actions close the drawer, like the native closedby attribute: any a backdrop click, a touch swipe toward its edge or Escape, closerequest only Escape, none neither.
fullWidthboolean—
Makes the drawer stretch to fill the full width of its parent container.
fullHeightboolean—
Makes the drawer stretch to fill the full height of its parent container.

Also accepts all <dialog> attributes.

  • It sets no id or aria-labelledby itself: name it with aria-labelledby pointing to your heading's id, or with aria-label. onCancel and onClose run after the internal handlers. ref points to the <dialog> element.
  • blurred (default true) blurs the page behind the drawer.
  • overlay (default true) dims the page; false makes the ::backdrop transparent while the drawer stays modal.
  • shadowed adds the surface shadow; fullWidth and fullHeight stretch the panel.
  • closedBy sets which user actions close the drawer, like the native closedby attribute: 'any' (a backdrop click, a touch swipe toward its edge, or Escape, the default), 'closerequest' (Escape only), or 'none'.
  • Closes on submit of a <form method="dialog"> inside it, also with closedBy='none'. The close goes through onChangeOpen(false), and the submit button's value becomes the dialog's returnValue.
  • With closedBy='any', a touch swipe toward the drawer's edge drags it and closes it past half its size or on a flick. Mouse drags are left for text selection.
  • Stays mounted only while open and while the close transition plays.

DrawerClose

Closes the drawer when clicked. It has no styles, icon, or default aria-label: render your own button inside it with asChild and label it.

PropTypeDefault
asChildboolean—
If true, renders the close action as its child element using Slot, so any button of your own closes the drawer.
refRef<HTMLButtonElement>—
Ref forwarded to the underlying button.

Also accepts all <button> attributes.

  • The close goes through onChangeOpen(false), so the close transition plays and a controlled parent can keep the drawer open.
  • Use it for a standalone close button, such as the X in a header. For buttons that answer the drawer (Cancel, Confirm, a returnValue), use a <form method="dialog">. Without asChild it renders type="button", so it also works inside a form of your own without submitting it; with asChild give your own button type="button".
minimal-composition.tsx · 43 lines
import { useId, type CSSProperties } from 'react';
import {
  Button,
  Drawer,
  DrawerClose,
  DrawerContent,
  DrawerTrigger,
  Heading,
  Icon,
  IconButton,
  Text,
} from '@vega-ui/react';

Hooks

useDrawerContext

Returns { open, changeOpen, position } for advanced wrappers and custom controls.

Types

  • DrawerProps
  • DrawerTriggerProps
  • DrawerContentProps
  • DrawerCloseProps

State Model

  • Open state can be controlled with open or uncontrolled with defaultOpen.
  • Every close request (backdrop click, swipe, Escape, DrawerClose click, <form method="dialog"> submit) goes through onChangeOpen(false); a controlled drawer stays open until open becomes false.
  • closedBy='none' on DrawerContent disables backdrop click, swipe, and Escape; close it with a button in a <form method="dialog"> or by changing open.
  • position uses logical sides that follow the writing direction: 'top-start', 'top', 'top-end', 'end-start', 'end', 'end-end', 'bottom-start', 'bottom', 'bottom-end', 'start-start', 'start', 'start-end'. In right-to-left text end is the left side.
  • Page scroll is locked while the drawer is open.
  • The drawer is always modal; overlay={false} only hides the dimming.