Drawer A sidebar panel that slides in from any edge of the viewport for navigation, forms, or supplementary content.
npx vayu-ui init #one time only
npx vayu-ui add -t drawer #with test case needs
Preview Code
Open Right Open Left Open Top Open Bottom
< Drawer side = "right" >
< Drawer.Trigger asChild >
< Button >Open Drawer</ Button >
</ Drawer.Trigger >
< Drawer.Overlay />
< Drawer.Content >
< Drawer.Header >
< Drawer.Title >Edit Profile</ Drawer.Title >
< Drawer.Description >Make changes to your profile here.</ Drawer.Description >
</ Drawer.Header >
< div className = "py-4" >
Profile form content...
</ div >
< Drawer.Footer >
< Drawer.Close asChild >
< Button >Save</ Button >
</ Drawer.Close >
</ Drawer.Footer >
</ Drawer.Content >
</ Drawer >
< Drawer side = "left" >
< Drawer.Trigger asChild >
< Button >Open Navigation</ Button >
</ Drawer.Trigger >
< Drawer.Overlay />
< Drawer.Content >
< Drawer.Header >
< Drawer.Title >Navigation</ Drawer.Title >
< Drawer.Description >Site navigation links.</ Drawer.Description >
</ Drawer.Header >
< nav className = "py-4" >
Navigation items...
</ nav >
</ Drawer.Content >
</ Drawer >
import { Drawer } from 'vayu-ui' ;
< Drawer side = "right" >
< Drawer.Trigger asChild >
< Button >Open</ Button >
</ Drawer.Trigger >
< Drawer.Overlay />
< Drawer.Content >
< Drawer.Header >
< Drawer.Title >Title</ Drawer.Title >
< Drawer.Description >Description goes here.</ Drawer.Description >
</ Drawer.Header >
< div className = "py-4" >{ /* Content */ }</ div >
< Drawer.Footer >
< Drawer.Close asChild >
< Button >Close</ Button >
</ Drawer.Close >
</ Drawer.Footer >
</ Drawer.Content >
</ Drawer >;
Drawer — Root container. Manages open/close state and provides context to all subcomponents. Supports controlled and uncontrolled usage.
Drawer.Trigger — Button that opens the drawer. Supports asChild to merge props onto a custom element.
Drawer.Overlay — Backdrop behind the drawer. Clicking it dismisses the drawer by default.
Drawer.Content — The slide-in panel with focus trapping and keyboard navigation. Includes a built-in close button.
Drawer.Header — Container for Drawer.Title and Drawer.Description.
Drawer.Title — Accessible heading rendered as an <h2>. Linked to the dialog via aria-labelledby.
Drawer.Description — Accessible description rendered as a <p>. Linked to the dialog via aria-describedby.
Drawer.Footer — Container for action buttons, pinned to the bottom of the drawer.
Drawer.Close — Button that closes the drawer. Supports asChild for custom elements.
Drawer.Portal — Portal wrapper for rendering the drawer outside the DOM tree.
Keyboard Support :
Escape — Closes the drawer.
Tab — Moves focus between interactive elements inside the drawer.
Shift + Tab — Moves focus backwards through interactive elements.
Focus is trapped within the drawer when open (circular tab navigation).
ARIA Attributes :
role="dialog" on Drawer.Content.
aria-modal="true" on Drawer.Content.
aria-labelledby on Drawer.Content links to Drawer.Title.
aria-describedby on Drawer.Content links to Drawer.Description.
aria-expanded on Drawer.Trigger reflects the open/closed state.
aria-haspopup="dialog" on Drawer.Trigger.
aria-hidden="true" on Drawer.Overlay.
Built-in close button has aria-label="Close drawer".
Focus Behavior :
When the drawer opens, focus moves to the first interactive element inside Drawer.Content.
Focus is trapped within the drawer until it closes.
When the drawer closes, focus returns to the trigger element.
Body scroll is locked while a modal drawer is open.
When a drawer opens, the screen reader announces the dialog (via role="dialog" and aria-modal="true") and reads the title (linked by aria-labelledby) and description (linked by aria-describedby). The overlay is hidden from the assistive technology tree (aria-hidden="true"). While the drawer is open, only content inside it is accessible to screen readers. When the drawer closes, focus returns to the trigger button and the previously visible content becomes accessible again.
Drawer/
├── Drawer.tsx # Root component with context provider and state management
├── DrawerTrigger.tsx # Trigger button that opens the drawer
├── DrawerOverlay.tsx # Modal backdrop with dismiss on click
├── DrawerContent.tsx # Slide-in panel with focus trapping and keyboard navigation
├── DrawerHeader.tsx # Container for title and description
├── DrawerFooter.tsx # Container for action buttons
├── DrawerTitle.tsx # Accessible heading linked to dialog
├── DrawerDescription.tsx # Accessible description linked to dialog
├── DrawerClose.tsx # Button that closes the drawer
├── DrawerPortal.tsx # Portal wrapper for DOM rendering
├── types.ts # TypeScript type definitions
├── index.ts # Re-exports all components and types
└── README.md # Component usage reference
Prop Type Default Description openboolean— Controlled open state. onOpenChange(open: boolean) => void— Callback when open state changes. defaultOpenbooleanfalseDefault open state for uncontrolled usage. side"left" | "right" | "top" | "bottom""right"Direction the drawer slides in from. modalbooleantrueWhether to lock body scroll and show overlay. childrenReactNode— Drawer subcomponents. classNamestring— Additional CSS classes.
Prop Type Default Description asChildbooleanfalseMerge props onto child element instead of rendering a button. classNamestring— Additional CSS classes.
Prop Type Default Description dismissiblebooleantrueWhether clicking the overlay closes the drawer. classNamestring— Additional CSS classes.
Prop Type Default Description trapFocusbooleantrueWhether to trap focus within the drawer when open. classNamestring— Additional CSS classes.
Prop Type Default Description classNamestring— Additional CSS classes.
Prop Type Default Description classNamestring— Additional CSS classes.
Prop Type Default Description classNamestring— Additional CSS classes.
Prop Type Default Description classNamestring— Additional CSS classes.
Prop Type Default Description asChildbooleanfalseMerge props onto child element instead of rendering a button. classNamestring— Additional CSS classes.
Prop Type Default Description childrenReactNode— Content to render inside the portal.