Drawer
A panel that slides in from a screen edge. It is an HTML popover: a DrawerToggle button opens and closes it through popovertarget, and the browser closes it on Escape or a click outside and shows it...
A panel that slides in from a screen edge. It is an HTML popover: a DrawerToggle button opens
and closes it through popovertarget, and the browser closes it on Escape or a click outside and
shows it in the top layer, above everything. None of that needs JavaScript, so a drawer works on
a prerendered page with scripts off - the mobile navigation menu, for example.
With JavaScript, it can also be controlled from state (isOpen / onClose), and while open it
moves focus inside, keeps Tab cycling within it, locks body scroll, and returns focus when it
closes. The surface is a Paper pinned to the chosen edge, with a slide-in
that respects prefers-reduced-motion; the page behind is dimmed through the popover's
::backdrop.
Usage
import { Drawer, DrawerToggle } from '@soroush.tech/design-system/Drawer'
<DrawerToggle drawer="nav" aria-label="Open navigation">
<Icon name="menu" />
</DrawerToggle>
<Drawer id="nav" anchor="left">
<Navigation />
<DrawerToggle drawer="nav" action="hide">Close</DrawerToggle>
</Drawer>
Controlled, with JavaScript:
const [isOpen, setIsOpen] = useState(false)
<Drawer id="filters" anchor="right" isOpen={isOpen} onClose={() => setIsOpen(false)}>
<Filters />
</Drawer>
The drawer's content is always in the page (hidden while closed), so it is server-rendered and
indexable; left / right drawers fill the window's height, top / bottom its width.
Examples
Default
Drawer
Slides in from the "left" edge. Press Escape or click outside to close.
const args: Partial<DrawerProps> = { anchor: 'left', elevation: 16, hasBackdrop: true, transitionDuration: 225, id: 'drawer', } <> <DrawerToggle drawer="drawer">Open drawer</DrawerToggle> <Drawer {...args} id="drawer"> <DrawerBody args={args} /> </Drawer> </>
Controlled
Drawer
Slides in from the "right" edge. Press Escape or click outside to close.
const args: Partial<DrawerProps> = { anchor: 'right', elevation: 16, hasBackdrop: true, transitionDuration: 225 } <ControlledDemo {...args} />