On this page
Drawer
A panel that slides in from the edge of the screen.
import { Drawer } from "@ninna-ui/overlays";pnpm add @ninna-ui/overlays@latestIncludes
@ninna-ui/core. CSS setup required.View source Usage
Import and use the Drawer component in your application.
import { Drawer } from "@ninna-ui/overlays";import { Button , Code } from "@ninna-ui/primitives";
export default function Example() { return ( <Drawer> <Drawer.Trigger asChild> <Button>Open Drawer</Button> </Drawer.Trigger> <Drawer.Content> <Drawer.Header>Title</Drawer.Header> <Drawer.Body>Content</Drawer.Body> <Drawer.Footer> <Drawer.Close asChild> <Button variant="ghost">Cancel</Button> </Drawer.Close> <Button>Save</Button> </Drawer.Footer> </Drawer.Content> </Drawer> );}Basic
A basic right-side drawer with header, body, and footer.
Live preview/ Default
Placements
Drawer can slide in from any edge: left, right, top, or bottom.
Live preview/ Default
Sizes
Drawer supports xs, sm, md, lg, xl, and full sizes.
Live preview/ Default
Prevent Close
Disable overlay click and Escape key to create persistent drawers.
Live preview/ Default
With Form
Drawer is ideal for side forms and settings panels.
Live preview/ Default
With Description
Add an accessible description to the drawer for better screen reader support.
Live preview/ Default
API Reference
Complete list of props for the Drawer component and its sub-components.
Drawer (Root)
| Prop | Type | Default | Description |
|---|---|---|---|
children* | ReactNode | — | Drawer content (Trigger, Content, etc.) |
open | boolean | — | Controlled open state |
defaultOpen | boolean | false | Default open state (uncontrolled) |
onOpenChange | (open: boolean) => void | — | Callback when open state changes |
modal | boolean | true | Whether the drawer blocks interaction with the rest of the page |
Drawer.Content
| Prop | Type | Default | Description |
|---|---|---|---|
placement | 'left' | 'right' | 'top' | 'bottom' | 'right' | Which edge the drawer slides from |
size | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | 'md' | Size of the drawer panel |
description | string | — | Accessible description for the drawer. Rendered as sr-only when provided. |
closeOnOverlayClick | boolean | true | Whether clicking the overlay closes the drawer |
closeOnEscape | boolean | true | Whether pressing Escape closes the drawer |
onEscapeKeyDown | (event: KeyboardEvent) => void | — | Callback when Escape key is pressed |
onPointerDownOutside | (event: Event) => void | — | Callback when pointer clicks outside content |
className | string | — | Additional CSS classes |
Drawer.Trigger
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as child element instead of wrapping button |
Drawer.Close
| Prop | Type | Default | Description |
|---|---|---|---|
asChild | boolean | false | Render as child element instead of default close button |
Accessibility
- Uses
role="dialog"witharia-modal="true" - Focus is trapped inside the drawer when open
- Focus returns to the trigger element when the drawer is closed
- Escape key closes the drawer by default (configurable)
- Overlay click closes the drawer by default (configurable)
- Supports all four placement directions with proper slide animations