A panel which slides in from the edge of the screen.
A Drawer is a panel that is typically overlaid on top of a page and slides in from the side. It contains a set of information or actions. Since the user can interact with the Drawer without leaving the current page, tasks can be achieved more efficiently within the same context.
import React, { useState } from 'react';
import { Button, Drawer } from 'antd';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
return (
<>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
<Drawer title="Basic Drawer" placement="right" onClose={onClose} open={open}>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};
export default App;
import React, { useState } from 'react';
import { Button, Drawer, Radio, Space } from 'antd';
import type { DrawerProps } from 'antd/es/drawer';
import type { RadioChangeEvent } from 'antd/es/radio';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const [placement, setPlacement] = useState<DrawerProps['placement']>('right');
const showDrawer = () => {
setOpen(true);
};
const onChange = (e: RadioChangeEvent) => {
setPlacement(e.target.value);
};
const onClose = () => {
setOpen(false);
};
return (
<>
<Space>
<Radio.Group value={placement} onChange={onChange}>
<Radio value="top">top</Radio>
<Radio value="right">right</Radio>
<Radio value="bottom">bottom</Radio>
<Radio value="left">left</Radio>
</Radio.Group>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
</Space>
<Drawer
title="Drawer with extra actions"
placement={placement}
width={500}
onClose={onClose}
open={open}
extra={
<Space>
<Button onClick={onClose}>Cancel</Button>
<Button type="primary" onClick={onClose}>
OK
</Button>
</Space>
}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};
export default App;
import React, { useState } from 'react';
import { PlusOutlined } from '@ant-design/icons';
import { Button, Col, DatePicker, Drawer, Form, Input, Row, Select, Space } from 'antd';
const { Option } = Select;
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
return (
<>
<Button type="primary" onClick={showDrawer} icon={<PlusOutlined />}>
New account
</Button>
<Drawer
title="Create a new account"
width={720}
onClose={onClose}
open={open}
bodyStyle={{ paddingBottom: 80 }}
extra={
<Space>
<Button onClick={onClose}>Cancel</Button>
<Button onClick={onClose} type="primary">
Submit
</Button>
</Space>
}
>
<Form layout="vertical" hideRequiredMark>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="name"
label="Name"
rules={[{ required: true, message: 'Please enter user name' }]}
>
<Input placeholder="Please enter user name" />
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="url"
label="Url"
rules={[{ required: true, message: 'Please enter url' }]}
>
<Input
style={{ width: '100%' }}
addonBefore="http://"
addonAfter=".com"
placeholder="Please enter url"
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="owner"
label="Owner"
rules={[{ required: true, message: 'Please select an owner' }]}
>
<Select placeholder="Please select an owner">
<Option value="xiao">Xiaoxiao Fu</Option>
<Option value="mao">Maomao Zhou</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="type"
label="Type"
rules={[{ required: true, message: 'Please choose the type' }]}
>
<Select placeholder="Please choose the type">
<Option value="private">Private</Option>
<Option value="public">Public</Option>
</Select>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={12}>
<Form.Item
name="approver"
label="Approver"
rules={[{ required: true, message: 'Please choose the approver' }]}
>
<Select placeholder="Please choose the approver">
<Option value="jack">Jack Ma</Option>
<Option value="tom">Tom Liu</Option>
</Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item
name="dateTime"
label="DateTime"
rules={[{ required: true, message: 'Please choose the dateTime' }]}
>
<DatePicker.RangePicker
style={{ width: '100%' }}
getPopupContainer={(trigger) => trigger.parentElement!}
/>
</Form.Item>
</Col>
</Row>
<Row gutter={16}>
<Col span={24}>
<Form.Item
name="description"
label="Description"
rules={[
{
required: true,
message: 'please enter url description',
},
]}
>
<Input.TextArea rows={4} placeholder="please enter url description" />
</Form.Item>
</Col>
</Row>
</Form>
</Drawer>
</>
);
};
export default App;
.site-form-in-drawer-wrapper {
position: absolute;
right: 0px;
bottom: 0px;
width: 100%;
padding: 10px 16px;
text-align: right;
background: #fff;
border-top: 1px solid #e9e9e9;
}
import React, { useState } from 'react';
import { Button, Drawer } from 'antd';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const [childrenDrawer, setChildrenDrawer] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
const showChildrenDrawer = () => {
setChildrenDrawer(true);
};
const onChildrenDrawerClose = () => {
setChildrenDrawer(false);
};
return (
<>
<Button type="primary" onClick={showDrawer}>
Open drawer
</Button>
<Drawer title="Multi-level drawer" width={520} closable={false} onClose={onClose} open={open}>
<Button type="primary" onClick={showChildrenDrawer}>
Two-level drawer
</Button>
<Drawer
title="Two-level Drawer"
width={320}
closable={false}
onClose={onChildrenDrawerClose}
open={childrenDrawer}
>
This is two-level drawer
</Drawer>
</Drawer>
</>
);
};
export default App;
import React, { useState } from 'react';
import type { DrawerProps, RadioChangeEvent } from 'antd';
import { Button, Drawer, Radio, Space } from 'antd';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const [placement, setPlacement] = useState<DrawerProps['placement']>('left');
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
const onChange = (e: RadioChangeEvent) => {
setPlacement(e.target.value);
};
return (
<>
<Space>
<Radio.Group value={placement} onChange={onChange}>
<Radio value="top">top</Radio>
<Radio value="right">right</Radio>
<Radio value="bottom">bottom</Radio>
<Radio value="left">left</Radio>
</Radio.Group>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
</Space>
<Drawer
title="Basic Drawer"
placement={placement}
closable={false}
onClose={onClose}
open={open}
key={placement}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};
export default App;
import React, { useState } from 'react';
import { Button, Drawer, theme } from 'antd';
const App: React.FC = () => {
const { token } = theme.useToken();
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
const containerStyle: React.CSSProperties = {
position: 'relative',
height: 200,
padding: 48,
overflow: 'hidden',
textAlign: 'center',
background: token.colorFillAlter,
border: `1px solid ${token.colorBorderSecondary}`,
borderRadius: token.borderRadiusLG,
};
return (
<div style={containerStyle}>
Render in this
<div style={{ marginTop: 16 }}>
<Button type="primary" onClick={showDrawer}>
Open
</Button>
</div>
<Drawer
title="Basic Drawer"
placement="right"
closable={false}
onClose={onClose}
open={open}
getContainer={false}
>
<p>Some contents...</p>
</Drawer>
</div>
);
};
export default App;
import React, { useState } from 'react';
import { Avatar, Col, Divider, Drawer, List, Row } from 'antd';
interface DescriptionItemProps {
title: string;
content: React.ReactNode;
}
const DescriptionItem = ({ title, content }: DescriptionItemProps) => (
<div className="site-description-item-profile-wrapper">
<p className="site-description-item-profile-p-label">{title}:</p>
{content}
</div>
);
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const showDrawer = () => {
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
return (
<>
<List
dataSource={[
{
id: 1,
name: 'Lily',
},
{
id: 2,
name: 'Lily',
},
]}
bordered
renderItem={(item) => (
<List.Item
key={item.id}
actions={[
<a onClick={showDrawer} key={`a-${item.id}`}>
View Profile
</a>,
]}
>
<List.Item.Meta
avatar={
<Avatar src="https://gw.alipayobjects.com/zos/rmsportal/BiazfanxmamNRoxxVxka.png" />
}
title={<a href="https://ant.design/index-cn">{item.name}</a>}
description="Progresser XTech"
/>
</List.Item>
)}
/>
<Drawer width={640} placement="right" closable={false} onClose={onClose} open={open}>
<p className="site-description-item-profile-p" style={{ marginBottom: 24 }}>
User Profile
</p>
<p className="site-description-item-profile-p">Personal</p>
<Row>
<Col span={12}>
<DescriptionItem title="Full Name" content="Lily" />
</Col>
<Col span={12}>
<DescriptionItem title="Account" content="AntDesign@example.com" />
</Col>
</Row>
<Row>
<Col span={12}>
<DescriptionItem title="City" content="HangZhou" />
</Col>
<Col span={12}>
<DescriptionItem title="Country" content="China🇨🇳" />
</Col>
</Row>
<Row>
<Col span={12}>
<DescriptionItem title="Birthday" content="February 2,1900" />
</Col>
<Col span={12}>
<DescriptionItem title="Website" content="-" />
</Col>
</Row>
<Row>
<Col span={24}>
<DescriptionItem
title="Message"
content="Make things as simple as possible but no simpler."
/>
</Col>
</Row>
<Divider />
<p className="site-description-item-profile-p">Company</p>
<Row>
<Col span={12}>
<DescriptionItem title="Position" content="Programmer" />
</Col>
<Col span={12}>
<DescriptionItem title="Responsibilities" content="Coding" />
</Col>
</Row>
<Row>
<Col span={12}>
<DescriptionItem title="Department" content="XTech" />
</Col>
<Col span={12}>
<DescriptionItem title="Supervisor" content={<a>Lin</a>} />
</Col>
</Row>
<Row>
<Col span={24}>
<DescriptionItem
title="Skills"
content="C / C + +, data structures, software engineering, operating systems, computer networks, databases, compiler theory, computer architecture, Microcomputer Principle and Interface Technology, Computer English, Java, ASP, etc."
/>
</Col>
</Row>
<Divider />
<p className="site-description-item-profile-p">Contacts</p>
<Row>
<Col span={12}>
<DescriptionItem title="Email" content="AntDesign@example.com" />
</Col>
<Col span={12}>
<DescriptionItem title="Phone Number" content="+86 181 0000 0000" />
</Col>
</Row>
<Row>
<Col span={24}>
<DescriptionItem
title="Github"
content={
<a href="http://github.com/ant-design/ant-design/">
github.com/ant-design/ant-design/
</a>
}
/>
</Col>
</Row>
</Drawer>
</>
);
};
export default App;
.site-description-item-profile-wrapper {
margin-bottom: 7px;
color: rgba(0, 0, 0, 0.65);
font-size: 14px;
line-height: 1.5715;
}
.ant-drawer-body p.site-description-item-profile-p {
display: block;
margin-bottom: 16px;
color: rgba(0, 0, 0, 0.85);
font-size: 16px;
line-height: 1.5715;
}
.site-description-item-profile-p-label {
display: inline-block;
margin-right: 8px;
color: rgba(0, 0, 0, 0.85);
}
import React, { useState } from 'react';
import { Button, Drawer, Space } from 'antd';
import type { DrawerProps } from 'antd/es/drawer';
const App: React.FC = () => {
const [open, setOpen] = useState(false);
const [size, setSize] = useState<DrawerProps['size']>();
const showDefaultDrawer = () => {
setSize('default');
setOpen(true);
};
const showLargeDrawer = () => {
setSize('large');
setOpen(true);
};
const onClose = () => {
setOpen(false);
};
return (
<>
<Space>
<Button type="primary" onClick={showDefaultDrawer}>
Open Default Size (378px)
</Button>
<Button type="primary" onClick={showLargeDrawer}>
Open Large Size (736px)
</Button>
</Space>
<Drawer
title={`${size} Drawer`}
placement="right"
size={size}
onClose={onClose}
open={open}
extra={
<Space>
<Button onClick={onClose}>Cancel</Button>
<Button type="primary" onClick={onClose}>
OK
</Button>
</Space>
}
>
<p>Some contents...</p>
<p>Some contents...</p>
<p>Some contents...</p>
</Drawer>
</>
);
};
export default App;
🚨 Note: v5 use rootClassName
& rootStyle
to config wrapper style instead of className
& style
in v4 to align the API with Modal.
Props | Description | Type | Default | Version |
---|---|---|---|---|
autoFocus | Whether Drawer should get focused after open | boolean | true | 4.17.0 |
afterOpenChange | Callback after the animation ends when switching drawers | function(open) | - | |
bodyStyle | Style of the drawer content part | CSSProperties | - | |
className | Config Drawer Panel className. Use rootClassName if want to config top dom style | string | - | |
closable | Whether a close (x) button is visible on top left of the Drawer dialog or not | boolean | true | |
closeIcon | Custom close icon | ReactNode | <CloseOutlined /> | |
contentWrapperStyle | Style of the drawer wrapper of content part | CSSProperties | - | |
destroyOnClose | Whether to unmount child components on closing drawer or not | boolean | false | |
extra | Extra actions area at corner | ReactNode | - | 4.17.0 |
footer | The footer for Drawer | ReactNode | - | |
footerStyle | Style of the drawer footer part | CSSProperties | - | |
forceRender | Pre-render Drawer component forcibly | boolean | false | |
getContainer | mounted node and display window for Drawer | HTMLElement | () => HTMLElement | Selectors | false | body | |
headerStyle | Style of the drawer header part | CSSProperties | - | |
height | Placement is top or bottom , height of the Drawer dialog | string | number | 378 | |
keyboard | Whether support press esc to close | boolean | true | |
mask | Whether to show mask or not | boolean | true | |
maskClosable | Clicking on the mask (area outside the Drawer) to close the Drawer or not | boolean | true | |
maskStyle | Style for Drawer's mask element | CSSProperties | {} | |
placement | The placement of the Drawer | top | right | bottom | left | right | |
push | Nested drawers push behavior | boolean | { distance: string | number } | { distance: 180 } | 4.5.0+ |
rootClassName | The class name of the container of the Drawer dialog | string | - | |
rootStyle | Style of wrapper element which contains mask compare to style | CSSProperties | - | |
style | Style of Drawer panel. Use bodyStyle if want to config body only | CSSProperties | - | |
size | preset size of drawer, default 378px and large 736px | 'default' | 'large' | 'default' | 4.17.0 |
title | The title for Drawer | ReactNode | - | |
open | Whether the Drawer dialog is visible or not | boolean | false | |
width | Width of the Drawer dialog | string | number | 378 | |
zIndex | The z-index of the Drawer | number | 1000 | |
onClose | Specify a callback that will be called when a user clicks mask, close button or Cancel button | function(e) | - |