Drawer
A side panel that opens on the start edge of the screen, for menus and filters.
Use Drawer for content that opens over the page from the side, such as a mobile menu or a filter panel. For a centred dialog, use Modal.
Example
import { useState } from 'react';
import { Drawer } from '@salla.sa/twilight-theme-engine/drawer';
import { Link } from '@salla.sa/twilight-theme-engine/common';
export function MobileMenu() {
const [open, setOpen] = useState(false);
return (
<>
<button onClick={() => setOpen(true)} aria-label="Menu">Menu</button>
<Drawer isOpen={open} onClose={() => setOpen(false)}>
<Drawer.Header onClose={() => setOpen(false)}>Menu</Drawer.Header>
<Drawer.Body>
<Link to="/products" onClick={() => setOpen(false)}>Products</Link>
</Drawer.Body>
</Drawer>
</>
);
}You own the open state: the drawer only asks you to close it through onClose.
API
| Prop | Type | Description |
|---|---|---|
isOpen | boolean | Whether the drawer is shown. Required. |
onClose | () => void | Called on Escape or backdrop click. Required. |
children | ReactNode | Drawer content. Required. |
size? | "sm" | "md" | "lg" | "full" | Width: w-64, w-80, w-96 or full width. Default: "md". |
closeOnBackdropClick? | boolean | Close when the backdrop is clicked. Default: true. |
closeOnEscape? | boolean | Close on the Escape key. Default: true. |
preventBodyScroll? | boolean | Lock page scroll while open. Default: true. |
className? | string | Class on the drawer panel. |
Parts: Drawer.Header, Drawer.Body and Drawer.Footer. Each accepts normal div attributes. Drawer.Header also takes showCloseButton (default true) and onClose.
Gotchas
- There is no
positionprop. The drawer opens on the left in left-to-right themes and on the right when the theme is RTL. - The close button in
Drawer.Headerappears only when you passonCloseto the header too. - It renders nothing while closed and during server rendering, so it never appears in the server HTML.
- While open it adds the class
menu-openedto<body>, and on close focus returns to the element that had it before. - It reads the theme direction, so it must be inside
TwilightProvider(your root route already is).
Next
Modalis the centred dialog with the same props.- Layout and components