Usage
Drawer displays content in a sliding panel anchored to either side of the viewport. It preserves the current context while keeping the main interface uncluttered. Built on Motion for smooth animations and Zustand for state management, Drawer supports multiple anchor positions, custom sizing, portal rendering, and controlled state management—making it ideal for sidebars, panels, and overlay content.
Among the most common—and controversial—matters that arise in interface design is when to use a drawer versus a modal dialog or even another page. Abide by these guidelines when determining when to use one or another.
Drawer’s chief advantage is that it keeps users in context—where they are on the page—without pushing them into a modal dialog or sending them to another page. In structured workflows where users need to view information side-by-side, drawers are essential.
The goal is to minimize cognitive overhead: show more information at once without crowding the interface. That’s why Drawer typically hovers over other elements (positioned absolutely) rather than rendering as an inline panel.
Drawer is tailor-made for use with DataTable for the reasons mentioned above. While users browse, filter, and search on the table, they click on a row that opens a drawer containing details about a particular entity—a recording, a protocol, a user—and in many cases contains a form for making modifications.
Dialog is ideal, adding intentional friction by removing the user from the context and requiring that they confirm their intent.
For extended workflows that require viewing multiple sources of information at once, use TakeoverModal. This is especially the case when a workflow is linked to a DataTable. Drawer, in fact, provides a perfect jump off point into a TakeoverModal: the instance of Drawer supplies high-level details with a CTA to enter a workflow in TakeoverModal.
Drawer section should use padding={2} (16px).
Default color at the Regular size.
Optionally add a badge to convey status or state to the right of the title and, if used, the counter.
Separators. A Drawer body may contain several sections; each should use borders that span to the edge of the drawer rather than a Separator, which respects horizontal padding.DataList for key-pair values, such as providing metadata about a call (e.g., title, summary, location, etc.).SegmentedControl to split content. If necessary, nest it in a Scrollable to support horizontal overflow—or, better yet, reduce the number of sections.Scrollable to sections with contents likely to overflow available space. Use smallScrollbar to keep the scrollbar narrow and scroll for scrollbarVisibility, such that it vanishes when the user isn't scrolling.Drawer footer should contain up to two CTA buttons on the right hand side (spaced apart by a gap of 2 , or 16px).
Placed flush left, a Badge can indicate the state of actions in the drawer, such as "draft" or "published." Use sparingly.
More frequently used is informational text, also flush left, with guidance or key information related to the workflows triggered with the CTA buttons.
Drawer occludes content on the page and must be dismissed to view what it hides. An exception is DataTable: when paired with Drawer, users can scroll horizontally behind the drawer to view each column.
A floating drawer is preferable when used with DataTable and in cramped interfaces.
overflow: clip, not overflow: hidden, so focus entering the animated drawer cannot scroll the surrounding page sideways. Inline drawers can also serve as conditionally visible panels in interfaces with sufficient space.
Drawer takes no zIndex; where it stacks follows from modal and placement:
showModal puts the panel in the top layer, above everything on the page, whatever its placement.Viewport or Container. show is not the top layer. The panel stacks at --z-overlay in the page's stacking order: above page content stacked lower (sticky headers, dropdown-level boxes) and below every top-layer surface, so a popover, menu, select or tooltip opened from inside the drawer, a toast, and a modal dialog all appear above it. The toast stack stays above non-modal drawers by design.Inline. The panel is in flow and stacks with its siblings.transform, filter, contain, will-change, or a positioned box with a z-index), a Viewport or Container panel is confined to that ancestor: --z-overlay orders it only inside it, and a Viewport panel is laid out against it instead of the viewport. So render an app-level drawer at the shell's root, through Drawer host. A remote that needs a page-level panel asks the shell's DrawerHost for it with navigation.openDrawer, or opens a modal drawer.
45rem, Drawer accommodates custom widths between 40rem and 67dvw. Override the default width if the purpose of the drawer is to showcase items of a large size, such as media or maps.
In addition to clicking the dismissal button, users can press the ESC key to dismiss a drawer.
Since auto-saving is generally unsupported, only enable clicking outside to dismiss if a drawer contains informational or read-only content.