Drawer
The Drawer component is a panel that slides out from the edge of the screen. It can be useful when you need users to complete a task or view some details without leaving the current page.
Import
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeading,
DrawerFooter,
DrawerBody,
DrawerCloseButton
} from "@recastui/react";
Usage
<Drawer><DrawerTrigger asChild><Button>Open Drawer</Button></DrawerTrigger><DrawerContent><DrawerHeading>Drawer Title</DrawerHeading><DrawerCloseButton /><DrawerBody>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</DrawerBody><DrawerFooter><div className='space-x-3'><Button size='sm'>Main Action</Button><Button size='sm' variant='ghost'>Secondary Action</Button></div></DrawerFooter></DrawerContent></Drawer>
Drawer placement positions
The Drawer can appear from any edge of the screen. Pass the position
prop and set it to top
, right
, bottom
, or left
. Defalut is left
.
() => {const [isOpen, setIsOpen] = useState(false);const [position, setPosition] = useState('left');const handlePositionClick = (newPosition) => {setPosition(newPosition);setIsOpen(true);};const positions = ['left', 'right', 'top', 'bottom'];return (<><div className='grid gap-2 grid-cols-2'>{positions.map((p) => (<ButtononClick={() => handlePositionClick(p)}key={p}>{`Open ${p} Drawer`}</Button>))}</div><Drawer open={isOpen} onOpenChange={setIsOpen} position={position}><DrawerContent><DrawerHeading>Drawer Title</DrawerHeading><DrawerCloseButton /><DrawerBody>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</DrawerBody><DrawerFooter><div className='space-x-3'><Button onClick={()=>setIsOpen(false)}>Close</Button><Button variant='ghost'>Secondary Action</Button></div></DrawerFooter></DrawerContent></Drawer></>);}
Drawer sizes
Pass the size prop if you need to adjust the size of the Drawer. Values can be xs
, sm
, md
, lg
, xl
, or full
. Default is xs
.
() => {const [isOpen, setIsOpen] = useState(false);const [size, setSize] = useState('xs');const handleSizeClick = (newSize) => {setSize(newSize);setIsOpen(true);};const sizes = ['xs', 'sm', 'md', 'lg', 'xl', 'full'];return (<><div className='grid gap-2 grid-cols-3'>{sizes.map((s) => (<ButtononClick={() => handleSizeClick(s)}key={s}>{`Open ${s} Drawer`}</Button>))}</div><Drawer open={isOpen} onOpenChange={setIsOpen} size={size}><DrawerContent><DrawerHeading>Drawer Title</DrawerHeading><DrawerCloseButton /><DrawerBody>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</DrawerBody><DrawerFooter><div className='space-x-3'><Button onClick={()=>setIsOpen(false)}>Close</Button><Button variant='ghost'>Secondary Action</Button></div></DrawerFooter></DrawerContent></Drawer></>);}
Focus on specific element
When a form is in the drawer, you might need to set focus on a specific element when the drawer opens. Pass the initialFocusRef
prop.
Without the initialFocusRef prop, the drawer will set focus on the first focusable element when it opens.
() => {const [isOpen, setIsOpen] = useState(false);const initialRef = React.useRef(null);return (<><Button onClick={()=>setIsOpen(true)}>Show Drawer</Button><Drawer initialFocus={initialRef} open={isOpen} onOpenChange={setIsOpen}><DrawerContent><DrawerHeading>Drawer Title</DrawerHeading><DrawerCloseButton /><DrawerBody><Button ref={initialRef}>This button has initial Focus</Button>Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.</DrawerBody><DrawerFooter><div className='space-x-3'><Button onClick={()=>setIsOpen(false)}>Close</Button><Button variant='ghost'>Secondary Action</Button></div></DrawerFooter></DrawerContent></Drawer></>);}
Props
Drawer
Prop | Type | Default | Description |
---|---|---|---|
initialOpen | boolean | false | The initial open state of the Modal (optional). |
open | boolean | - | The open state of the Modal in controlled mode. |
onOpenChange | (open: boolean) => void | - | A callback function for handling open state changes in controlled mode. |
initialFocus | React.RefObject<HTMLElement> | - | Ref to the initial element to focus when the modal opens. |
returnFocus | boolean | true | Return focus to the element that triggered modal to open when the modal closes. |
size | “xs” | “sm” | “md” | “lg” | “xl” | “full” | “md” | The size of the modal. |
position | “left” | “right” | “top” | “bottom” | “left” | The placement position of the drawer. |
children | React.ReactNode | - | Children passed to the subcomponents. |
className | string (optional) | - | Additional class names to apply |
DrawerContent
Prop | Type | Default | Description |
---|---|---|---|
className | string (optional) | - | Additional class names to apply |
overlayClassName | string (optional) | - | Additional class names to apply to the Overlay element |
children | React.ReactNode | - | Children passed to the component. |
DrawerTrigger
Prop | Type | Default | Description |
---|---|---|---|
asChild | boolean | false | Children passed to the component. |
className | string (optional) | - | Additional class names to apply |
children | React.ReactNode | - | Children passed to the component. |
DrawerTrigger, DrawerHeading, DrawerBody, DrawerFooter & DrawerCloseButton
Prop | Type | Description |
---|---|---|
children | React.ReactNode | The children for the subcomponents |
className | string (optional) | Additional class names to apply |
Accessibility
This Drawer component has been designed to follow best practices for accessibility:
- Focus is trapped within the drawer when it is open.
- Focus is automatically set to the first enabled element or the element specified by
initialFocus
. - When the drawer closes, focus returns to the element that was focused before the drawer was activated, or the element specified by
finalFocusRef
. - Clicking on the overlay closes the drawer.
- Pressing the
Esc
key closes the drawer. - Scrolling is blocked on the elements behind the drawer.
- The drawer is rendered in a portal attached to the end of
document.body
, making it easy to addaria-hidden
to its siblings. aria-modal
is set totrue
on theDrawerContent
component.aria-labelledby
is set to theid
of theDrawerHeading
component.aria-describedby
is set to theid
of theDrawerBody
component.