Drawer
The Drawer component is a modal component that can be positioned to the left, right, top or bottom of the viewport. It can be used to display additional information or actions without leaving the current screen. It renders contents similar to the Modal component and supports a header, body, fixed footer and icon.
function Example() {const [show, setShow] = useState(false);const handleClose = () => setShow(false);const handleShow = () => setShow(true);return (<><Button variant="primary" onClick={handleShow}>Toggle</Button><Drawer show={show} onHide={handleClose}><Drawer.HeadercloseButtonrenderIcon={() => (<Drawer.Icon><span className="icon-message-circle-02" /></Drawer.Icon>)}title="Title"subtitle="Subtitle"/><Drawer.Body>Some text as placeholder. In real life you can have the elements you have chosen. Like,text, images, lists, etc.</Drawer.Body><Drawer.Footer><Button onClick={handleClose} variant="outline-secondary">Cancel</Button><Button onClick={handleClose}>Save</Button></Drawer.Footer></Drawer></>);}
Variations, Scrolling, and Tooltips
The Drawer components allow for customization similar to Modal. The body supports the prop bordered
which will render a variant of the body that places a border at the top and bottom of the body.
This example also shows using the scrollable
prop on the body to allow for scrolling within the body.
❗Tooltips need to be attached to a container outside of the Drawer.Body. Here the Tooltip on the Select label is attached to the Drawer.Header.
function Example() {const [show, setShow] = useState(false);const [isSlidden, setIsSlidden] = useState(false);const drawerHeaderRef = useRef(null);const handleClose = () => setShow(false);const handleShow = () => setShow(true);return (<><Button variant="primary" onClick={handleShow}>Toggle</Button><Drawer show={show} onHide={handleClose} placement="end"><Drawer.HeadercloseButtonrenderIcon={() => (<Drawer.Icon variant="danger"><span className="icon-placeholder" /></Drawer.Icon>)}title="Title"ref={drawerHeaderRef}/><Drawer.Body bordered scrollable><Form footerRenderer={() => null}><FormField><Selectname="select"label={<div className="d-flex"><span>Label</span><Tooltip title="I am a tooltip" container={() => drawerHeaderRef.current}><span className="ms-3 icon-help-circle" /></Tooltip></div>}><Item key="one">One</Item><Item key="two">Two</Item><Item key="three">Three</Item></Select></FormField>{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].map((i) => (<FormField key={i}><TextFieldname={`text${i}`}label={<LabelrenderAction={() => (<Button variant="link" className="p-0" onClick={() => setIsSlidden(true)}>Show more</Button>)}>Field {i}</Label>}/></FormField>))}</Form><Drawer.Slide show={isSlidden} onClickBack={() => setIsSlidden(false)}><p>More stuff related to Field 1</p><p>This could be additional fields, supplemental info, etc.</p>{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16].map((i) => (<TextField key={`slide-${i}`} name={`text${i}`} label="Text Field" />))}<p>This could be additional fields, supplemental info, etc.</p></Drawer.Slide></Drawer.Body><Drawer.Footer><Button onClick={handleClose} variant="outline-secondary">Cancel</Button><Button onClick={handleClose}>Save</Button></Drawer.Footer></Drawer></>);}
Sizes
The size of the Drawer can be customized. However, all Drawers will be full screen below the medium breakpoint.
function Example({ size }) {const [show, setShow] = useState(false);const handleClose = () => setShow(false);const handleShow = () => setShow(true);return (<><Button variant="primary" onClick={handleShow} className="mb-2">Toggle {size}</Button><Drawer show={show} onHide={handleClose} size={size}><Drawer.Header title={size} /><Drawer.Body bordered>Body</Drawer.Body><Drawer.Footer><Button onClick={handleClose} variant="outline-secondary">Cancel</Button><Button onClick={handleClose}>Save</Button></Drawer.Footer></Drawer></>);}render(['sm', 'md', 'lg', 'xl'].map((size) => <Example size={size} />));
Responsive Footers
Responsive footers will adjust the display order of their button children below the small breakpoint.
function Example() {const [show, setShow] = useState(false);const handleClose = () => setShow(false);const handleShow = () => setShow(true);return (<><Button variant="primary" onClick={handleShow} className="mb-2">Toggle</Button><Drawer show={show} onHide={handleClose}><Drawer.Header title="Reponsive Footer" /><Drawer.Body bordered>Body</Drawer.Body><Drawer.Footer responsive><Button onClick={handleClose} variant="outline-secondary">Cancel</Button><Button onClick={handleClose}>Save</Button></Drawer.Footer></Drawer></>);}
With DrawerSlide
The DrawerSlide component lets you display additional content in a Drawer. When shown, it will slide in and cover the main content and footer of your Drawer.
function Example() {const [show, setShow] = useState(false);const [isSlidden, setIsSlidden] = useState(false);const [isSliddenToo, setIsSliddenToo] = useState(false);return (<><Button onClick={() => setShow(true)}>Toggle Drawer</Button><Drawer show={show} onHide={() => setShow(false)} placement="end"><Drawer.HeadercloseButtonrenderIcon={() => (<Drawer.Icon><span className="icon-placeholder" /></Drawer.Icon>)}title="Title"subtitle="Subtitle"/><Drawer.Body bordered><Form footerRenderer={() => null}><FormField><TextFieldname="text"label={<LabelrenderAction={() => (<Button variant="link" className="p-0" onClick={() => setIsSlidden(true)}>Show more</Button>)}>Field 1</Label>}/></FormField><FormField><TextFieldname="text"label={<LabelrenderAction={() => (<Button variant="link" className="p-0" onClick={() => setIsSliddenToo(true)}>Show more</Button>)}>Field 2</Label>}/></FormField></Form><Drawer.Slide show={isSlidden} onClickBack={() => setIsSlidden(false)}><p>More stuff related to Field 1</p><p>This could be additional fields, supplemental info, etc.</p></Drawer.Slide><Drawer.Slide show={isSliddenToo} onClickBack={() => setIsSliddenToo(false)}><p>More stuff related to Field 2</p><p>This could be additional fields, supplemental info, etc.</p></Drawer.Slide></Drawer.Body><Drawer.Footer><Button variant="outline-secondary" onClick={() => setShow(false)}>Cancel</Button><Button>Submit</Button></Drawer.Footer></Drawer></>);}
Using Tabs
function Example() {const [show, setShow] = useState(false);const [activeTabId, setActiveTabId] = useState('Ownership');const handleClose = () => setShow(false);const handleShow = () => setShow(true);const tabsList = [<Tab key="Ownership" id="Ownership">Ownership</Tab>,<Tab key="Fees" id="Fees">Fees</Tab>,<Tab key="Realization" id="Realization">Realization</Tab>,<Tab key="Holdings" id="Holdings">Holdings</Tab>,];const tabContents = useMemo(() => {switch (activeTabId) {case 'Ownership':return 'Ownership Content';case 'Fees':return 'Fees Content';case 'Realization':return 'Realization Content';case 'Holdings':return 'Holdings Content';default:return null;}}, [activeTabId]);return (<><Button variant="primary" onClick={handleShow}>Toggle</Button><Drawer show={show} onHide={handleClose}><Drawer.HeadercloseButtonrenderIcon={() => (<Drawer.Icon><span className="icon-message-circle-02" /></Drawer.Icon>)}title="Title"subtitle="Subtitle"className="pb-0"/><Drawer.Body className="px-0"><Tabsvariant="tabs"tabs={tabsList}activeTabId={activeTabId}onTabClick={(event, id) => {setActiveTabId(id);}}className="px-4"></Tabs><div className="border-top px-4 py-3" style={{ marginTop: 1 }}>{tabContents}</div></Drawer.Body><Drawer.Footer><Button onClick={handleClose} variant="outline-secondary">Cancel</Button><Button onClick={handleClose}>Save</Button></Drawer.Footer></Drawer></>);}
Props
Drawer
DrawerHeader
The DrawerHeader supports a static set of props to render title, subtitle, and icon in a consistent manner. It also supports rendering children for more customization.
DrawerBody
DrawerFooter
The DrawerFooter component will automatically adjust the display of the buttons within such that they stack.
DrawerSlide
The DrawerSlide component allows you to slide in secondary content in a Drawer.