Preview
Design guidance
Use a drawer to create an object, apply filters, open workspace navigation, inspect details, or review a collection while keeping the current page in view. Placement, size, and modality are separate choices. Use a title that names the task, or an accessible Popup label for a button-only action sheet. Add a description only when it helps the user complete that task. For a non-modal drawer, omit the Backdrop so the page stays interactive.
The viewport keeps an 8px gap from each screen edge, with safe-area and virtual-keyboard insets applied where they take more space. Bottom and top sheets are capped at 460px. Side drawers are 400px wide. Both fit the available space on small screens. Override --drawer-width on the Popup when a product needs a different width. Header padding is 16px on each side. Core has no top padding, so the content starts 16px after the header. Footer actions stack vertically and fill the content width. The footer uses the shared subtle surface (050 in light mode) by default. Set --drawer-footer-background on a Popup or Footer to change it, or use the Footer’s native style.background.
For a footer that blends into the body, use a normal style override:
Installation
Install Drawer. The examples also compose Button, ButtonGroup, Field, Input, InputGroup, Item, Combobox, DatePicker, Textarea, Select, AlertDialog, and Composer. Install those owners when you copy an example; campaign data and state stay in the caller.
Basic usage
The trigger and title give the dialog an accessible name. Grip is optional. Without it, Popup has no grip padding. A direct-child Grip adds 4px at its edge. Side drawers reserve the 16px grip lane plus this 4px along the full edge, so Header, Core, and Footer share the same inset. Grip stays at the top, aligned with the Header row. The other three Popup edges keep their normal padding. Keep Grip outside Content so mouse users can drag it while selecting text. Touch users can swipe the sheet; scrollable content keeps normal scrolling.
Structures
Drawer.Root owns open state and modal behavior. Drawer.Trigger opens it. Drawer.Portal places the overlay outside the page layout. Drawer.Viewport owns placement and the screen-edge gap; it contains Drawer.Backdrop for modal use and Drawer.Popup. Add optional Drawer.Grip and one Drawer.Content as Popup siblings. Grip floats over the current row and adds only 4px along its full edge; normal 16px content padding becomes 20px on that edge. For a bottom sheet this is the top edge; for a top sheet it is the bottom. Side drawers inset all three regions together along the opening edge, with the grip at the top. Each region keeps its normal 16px content padding. Compose Drawer.Header for the title, optional description, and close control; Drawer.Core owns padded, scrollable task content; and Drawer.Footer holds stacked full-width actions, with the primary action first. Side drawers pin the footer while the Core scrolls. Top and bottom drawers hug their content until the available height requires Core scrolling. Drawer.Close can wrap a canonical Button or IconButton.
Nested Drawer.Root instances belong inside the parent Content; the examples place the child Trigger in the parent Footer as its primary CTA. Base UI keeps the parent mounted and restores focus when the child closes. Its native nested depth and frontmost-height values drive the stacked presentation. Drawer.VirtualKeyboardProvider manages keyboard-aware focus and scroll for form drawers. Drawer.SwipeArea can open a drawer by touch; always keep a visible trigger as an alternative. Drawer.IndentBackground and Drawer.Indent are an opt-in page treatment. They do not constrain a portal. For a contained panel, pass the positioned scene element to Drawer.Portal container={scene} and add ui-drawer-viewport--contained to its Viewport. The inset example keeps its backdrop and drawer inside that scene; its non-modal state leaves the rest of this page available.
Examples
Placement, modality, Grip, snap points, and content are independent choices. Each example combines these properties for a task; campaign data and state belong to the caller.
| Property | Example | Owner or state |
|---|---|---|
| Placement | Left navigation, right filters, top saved prompts, bottom source details | Caller content and swipeDirection |
| Grip | Optional left and right grips | Direct Popup child |
| Snap points | Compact and expanded image collection | Base UI gesture and snap state |
| Containment | Indented source details | Local portal container |
| Modality | Non-modal assistant and modal task drawers | modal and Backdrop |
Placement
The swipe direction matches the edge where each drawer opens. The right, left, top, and bottom previews use independent content and state. Navigation uses canonical Button controls. Base UI owns Drawer gesture and snap state; each caller owns collection changes such as adding and removing images.
Right · Task filters
Filter campaign tasks by search, status, assignee, due date, and priority. Apply updates the results. Cancel keeps the applied filters. Reset edits the draft back to its defaults.
6 of 6 tasks shown
- Review hero copyNora Nguyen · In progress · High priority
- Approve shot listYou · To do · High priority
- Upload product cutoutsAlex Rivera · To do · Normal priority
- Schedule launch emailsNora Nguyen · To do · Normal priority
- Publish campaign briefYou · Done · Normal priority
- Export email cropsAlex Rivera · To do · High priority
Left · Navigation
Open workspace sections and recent campaigns. Canonical Button controls use fixed icon lanes, mark the current destination, close the drawer, and update the visible page section.
Campaigns
- Trailpack spring launch
- Autumn layers
- Everyday carry
Top · Saved prompts
Select one of three saved instructions and insert it into the visible multiline draft. Cancel and Close keep the previous inserted text.
Spring campaign
12 assets · Draft
Write a launch email for the Trailpack.
Use the approved campaign brief. Include the 14L capacity and recycled nylon shell.
Bottom · Controlled source
Open the full launch brief, then show its contents in the page. This is a controlled bottom drawer with local result state.
Optional grip
Use Grip only when users need a visible drag target. It stays outside Content so mouse selection remains available.
Fieldwork / Spring campaign
Create launch copy and choose campaign images from the approved brief.
Snap points
Keep this non-modal image collection open while browsing. Its count, order, and contents update together. The Core grows between the header and pinned footer, which stays at the visible bottom. Base UI owns Drawer gesture and snap state; the caller owns adding and removing images. Use in campaign carries the current selection into the page. Images are local example assets.
Golden hour
Lakeside
Ridge line
Forest canopy
Open water
Alpine forestNested drawers
Each placement opens four levels: Preferences → Security settings → Session settings → Trusted device. The full-width footer action opens the next level. Back closes one level and restores the previous panel. Top and bottom keep an 8px parent strip.
Indented page
The contained portal shows source file facts and one Done action. Its short content leaves the page indent visible around the sheet.
Fieldwork / Spring campaign
Review the approved source before you draft campaign copy.
Modality and related behavior
Non-modal assistant
The page stays interactive while the assistant shows a launch-email draft and accepts a local revision request.
Keyboard-aware draft
The virtual keyboard provider keeps the focused field and action in reach.
Swipe to open
The edge gesture has a visible button alternative.
Fieldwork / Spring campaign
Use the Trailpack brief while you draft launch copy and review campaign backgrounds.
Unsaved changes
Saving keeps the text in the saved result. Discard clears it. Keep editing retains the input.
Action sheet
Use a vertical ButtonGroup with outline Buttons. Nest groups to separate related actions, conversation management, and Cancel. This sheet has no grip, header, or footer; aria-label names the dialog. Copy failure closes the sheet and shows an error on the page.
Detached triggers
Detached triggers open the same panel from separate caller locations.
Responsive placement
Keep the drawer on the right on wide screens and place it at the bottom on narrow screens.
API reference
| Prop | Type | Default | Description |
|---|---|---|---|
Grip | HTML div props and ref | Optional direct child of Popup, outside Content; aria-hidden by default. Floats absolutely in the current row; adds 4px along the full grip edge, with no separate row. Side grips align with the Header row; Header, Core, and Footer share the edge inset. | |
Header | HTML header props and ref | Optional compact title, description and caller-composed close control. Shares the grip-edge inset with Core and Footer. | |
Core | HTML div props and ref | Owns body scrolling; fills side drawers and grows between Header and pinned Footer in snap drawers. | |
Footer | HTML footer props and ref | Optional stacked full-width actions; stays at the visible bottom in snap and side drawers. Background defaults to the shared subtle surface; override --drawer-footer-background or native style.background. |
Drawer re-exports the installed Base UI parts and keeps its modal, focus, swipe, nested, and snap behavior. Header, Core, and Footer are forwarded native HTML regions with their matching HTML attributes and refs. All three are optional; a button-only action sheet can place ButtonGroup directly inside Content. Grip forwards native div attributes and its ref, is hidden from assistive technology by default, and provides no separate gesture engine. Place it outside Content so mouse drags reach Base UI Viewport. Content preserves mouse text selection; touch swipes and scroll arbitration remain Base UI behavior. See the Base UI Drawer API for inherited props and state.
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | Whether the drawer is open. | |
defaultOpen | boolean | false | Whether the drawer starts open. |
modal | boolean | "trap-focus" | true | Controls focus trapping, page scroll lock, and outside interaction. |
swipeDirection | "up" | "down" | "left" | "right" | "down" | The direction used to dismiss the drawer. |
snapPoints | DrawerSnapPoint[] | Snap offsets as viewport fractions, numeric pixel values, or px/rem strings. | |
snapPoint | DrawerSnapPoint | null | The controlled active snap point. | |
handle | Drawer.Handle<Payload> | Connects a Root with detached triggers. | |
onOpenChange | (open, eventDetails) => void | Called when open state changes. The event details can cancel a close. |