UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

336 lines (291 loc) 14.4 kB
--- localeCode: en-US order: 80 category: Show title: SideSheet subTitle: SideSheet icon: doc-sidesheet brief: An overlay panel that slides out from the edge of the screen, typically used to host secondary action pages. --- ## Demos ### How to import ```jsx import import { SideSheet } from '@douyinfe/semi-ui'; ``` ### Basic Usage By default, SideSheet slides from the right side of the screen and could be closed by clicking on the mask. ```jsx live=true import React, { useState } from 'react'; import { SideSheet, Button } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const change = () => { setVisible(!visible); }; return ( <> <Button onClick={change}>Open SideSheet</Button> <SideSheet title="Sidesheet" visible={visible} onCancel={change}> <p>This is the content of a basic sidesheet.</p> <p>Here is more content...</p> </SideSheet> </> ); }; ``` ### Placement You could use `placement` to set the position from which SideSheet comes in, supporting one of `top`, `bottom`, `left`, `right`。 ```jsx live=true import React, { useState } from 'react'; import { SideSheet, RadioGroup, Radio, Button } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const change = () => { setVisible(!visible); }; const [placement, setPlacement] = useState('right'); const changePlacement = e => { setPlacement(e.target.value); }; return ( <> <RadioGroup onChange={changePlacement} value={placement}> <Radio value={'right'}>right</Radio> <Radio value={'left'}>left</Radio> <Radio value={'top'}>top</Radio> <Radio value={'bottom'}>bottom</Radio> </RadioGroup> <br /> <br /> <Button onClick={change}>Open SideSheet</Button> <SideSheet title="Sidesheet" visible={visible} onCancel={change} placement={placement}> <p>This is the content of a basic sidesheet.</p> <p>Here is more content...</p> </SideSheet> </> ); }; ``` ### Size You could use `size` to set the size of SideSheet, supporting one of `small`(448px), `medium`(684px), and `large`(920px). Only takes effects when `placement` is set to `left` or `right`. If the default size does not meet your needs, you can also set the width by setting the `width` property, for example `width={900}` / `width={'800px'}` ```jsx live=true import React, { useState } from 'react'; import { SideSheet, RadioGroup, Radio, Button } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const change = () => { setVisible(!visible); }; const [size, setSize] = useState('small'); const changeSize = e => { setSize(e.target.value); }; return ( <> <RadioGroup onChange={changeSize} value={size}> <Radio value={'small'}>small</Radio> <Radio value={'medium'}>medium</Radio> <Radio value={'large'}>large</Radio> </RadioGroup> <br /> <br /> <Button onClick={change}>Open SideSheet</Button> <SideSheet title="SideSheet" visible={visible} onCancel={change} size={size}> <p>This is the content of a basic sidesheet.</p> <p>Here is more content...</p> </SideSheet> </> ); }; ``` ### Non-blocking Workflow You could set `mask={false}` to continue working on the area outside SideSheet. <Notice title='Tips'> By default, if you are not setting `getPopupContainer`, SideSheet is rendered inside body. If you want body element to be able to scroll, you could set disableScroll to false and the component will not add `overflow: hidden` to it. </Notice> ```jsx live=true import React, { useState } from 'react'; import { SideSheet, Button, TextArea } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const [value, setValue] = useState(''); return ( <> <Button onClick={() => setVisible(true)}>Open SideSheet</Button> <TextArea placeholder="Please enter something" onChange={value => setValue(value)} style={{ marginTop: 12 }}/> <SideSheet title="SideSheet" visible={visible} onCancel={() => setVisible(false)} mask={false} disableScroll={false}> <p>Here is what you entered: </p> <p>{value}</p> </SideSheet> </> ); }; ``` ### Rendered Inside Container You could use `getPopupContainer` to render SideSheet in targeted DOM. <Notice title='Tips'> The container must have `overflow: hidden` to avoid animated SideSheet overflows. </Notice> ```jsx live=true import React, { useState } from 'react'; import { SideSheet, Button } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const [value, setValue] = useState(''); const getContainer = () => { return document.querySelector('.sidesheet-container'); }; return ( <div style={{ height: 320, overflow: 'hidden', position: 'relative', border: '1px solid var(--semi-color-border)', borderRadius: 2, padding: 24, textAlign: 'center', background: 'var(--semi-color-fill-0)', }} className="sidesheet-container" > <span>Render in this</span> <br /> <br /> <Button onClick={() => setVisible(true)}>Open SideSheet</Button> <SideSheet title="SideSheet" visible={visible} onCancel={() => setVisible(false)} width={220} getPopupContainer={getContainer} > <p>This is the content of a basic sidesheet.</p> <p>Here is more content...</p> </SideSheet> </div> ); }; ``` ### Customized Content Use `title`, `footer` and other Semi Components, you could create customized information display layers. ```jsx live=true hideInDSM import React, { useState } from 'react'; import { SideSheet, Button, Typography, Banner, Form } from '@douyinfe/semi-ui'; () => { const [visible, setVisible] = useState(false); const show = () => { setVisible(true); }; const handleCancel = (e) => { setVisible(false); }; const { DatePicker, Select, Radio, RadioGroup, } = Form; const footer = ( <div style={{ display: 'flex', justifyContent: 'flex-end' }}> <Button style={{ marginRight: 8 }}>Reset</Button> <Button theme="solid">Submit</Button> </div> ); return ( <> <Button onClick={show}>More Information</Button> <SideSheet title={<Typography.Title heading={4}>Create New Package</Typography.Title>} headerStyle={{ borderBottom: '1px solid var(--semi-color-border)' }} bodyStyle={{ borderBottom: '1px solid var(--semi-color-border)' }} visible={visible} footer={footer} onCancel={handleCancel} > <Form> <DatePicker field="date" type="dateTime" initValue={new Date()} style={{ width: 272 }} label={{ text: 'Created Time', required: true }} /> <RadioGroup field="type" label="Target Operating System" direction="horizontal" initValue={'all'} > <Radio value="all">All</Radio> <Radio value="ios">iOS</Radio> <Radio value="android">Android</Radio> <Radio value="web">Web</Radio> </RadioGroup> <RadioGroup field="origin" label="Package Origin" direction="horizontal" initValue={'scm'}> <Radio value="scm">Uploaded From SCM</Radio> <Radio value="manual">Uploaded Manually</Radio> </RadioGroup> <Banner fullMode={false} icon={null} closeIcon={null} bordered description={ <Typography.Text> Software Config Management (SCM) is a platform for publish and manage code versions. You can compile and manage code versions in this platform. </Typography.Text> } /> <br /> <Select field="users" label={{ text: 'Created User', required: true }} style={{ width: 560 }} multiple initValue={['1', '2', '3', '4']} > <Select.Option value="1">Tianyi Lee</Select.Option> <Select.Option value="2">Chen Qu</Select.Option> <Select.Option value="3">Yan Cai</Select.Option> <Select.Option value="4">Wenzhuo Cui</Select.Option> </Select> </Form> </SideSheet> </> ); }; ``` ## API Reference | Properties | Instructions | type | Default | Version | | --- |----------------------------------------------------------------------------------------------------------------------------| --- | --- | --- | | afterVisibleChange | Callback function when animation of SideSheet ends | (isVisible: boolean) => void | - | - | | bodyStyle | Content style | CSSProperties | - | - | | className | Class name | string | - | - | | closable | Toggle whether to show close button | boolean | true | - | | closeIcon | Icon for close button | ReactNode | <IconClose /\> | - | | closeOnEsc | oggle whether to allow close modal by keyboard event Esc | boolean | false | - | | disableScroll | Toggle whether to add `overflow: hidden` to document.body element. Only works when not setting `getPopupContainer` | boolean | true | - | | footer | Footer | ReactNode | null | - | | getPopupContainer | Container where to render SideSheet inside, you need to set 'position: relative` This will change the DOM tree position, but not the view's rendering position. | () => HTMLElement | - | - | | headerStyle | Header style | CSSProperties | - | - | | height | Height, takes effect when `placement` is set to `top` or `bottom` | number \| string | 400 | - | | keepDOM | Keep components inside when closing sideSheet | boolean | false | | mask | Toggle whether to show mask. When `mask={false}`, you could continue operations outside SideSheet | boolean | true | - | | maskClosable | Toggle whether to allow closing when clicking mask | boolean | true | - | | maskStyle | Mask style | CSSProperties | - | - | | motion | Toggle whether to turn on animation | boolean | true | - | | placement | Sliding position, one of `top`, `bottom`, `left`, `right` | string | `right` | - | | size | Size, one of `small`(448px), `medium`(684px), `large`(920px), only take effects when placement is set to `left` or `right` | string | `small` | - | | style | Inline style | CSSProperties | - | - | | title | Title | ReactNode | - | - | | visible | Toggle visibility of the SideSheet | boolean | false | - | | width | Width, takes effect when `placement` is set to `left` or `right` | number \| string | 448 | - | | zIndex | Z-index value for SideSheet | number | 1000 | - | | onCancel | Callback function when clicking cancel button | (e: MouseEvent) => void | - | - | ## Accessibility ### ARIA - SideSheet has a `dialog` role to indicate that it is a pop-up component, and the internal header has a `heading` role to indicate that it is a header. ## Design Tokens <DesignToken/>