Sheet (Drawer)
- 组件说明:侧边面板,用于表单、详情视图或辅助内容展示。支持四个方向:上、右(默认)、下、左。基于 Radix Dialog。别名
Drawer。 - 当前状态:支持声明式(trigger 作为 children)和配置式(title/content/footer)两种模式,以及命令式
Sheet.open()API。 - 实现约定:
ui/sheet封装 Radix Dialog primitive,design 层提供配置式 API、方向/宽度控制与命令式弹层能力。
基础用法
通过 props 传入 title、content、footer,触发器作为 children 传入。
结果
Loading...
实时编辑器
render( <div style={{ padding: '40px 0' }}> <Sheet title="个人资料" content={ <div style={{ padding: '0 16px', flex: 1 }}> <p style={{ fontSize: 14, color: '#6b7280', marginBottom: 8 }}>查看和编辑个人信息。</p> <p>姓名:张三</p> <p>邮箱:zhangsan@example.com</p> </div> } footer={ <div style={{ display: 'flex', gap: 8, justifyContent: 'flex-end' }}> <Button variant="secondary">取消</Button> <Button>保存</Button> </div> } > <Button>打开面板</Button> </Sheet> </div>, )
方向变体
通过 side 控制面板滑出方向,默认为 right。
结果
Loading...
实时编辑器
render( <div style={{ display: 'flex', gap: 12, padding: '40px 0', flexWrap: 'wrap' }}> <Sheet side="right" title="右侧面板" content={<div style={{ padding: '0 16px', flex: 1 }}>从右侧滑出(默认)。</div>}> <Button variant="secondary">右</Button> </Sheet> <Sheet side="left" title="左侧面板" content={<div style={{ padding: '0 16px', flex: 1 }}>从左侧滑出。</div>}> <Button variant="secondary">左</Button> </Sheet> <Sheet side="top" title="顶部面板" content={<div style={{ padding: '0 16px' }}>从顶部滑出。</div>}> <Button variant="secondary">上</Button> </Sheet> <Sheet side="bottom" title="底部面板" content={<div style={{ padding: '0 16px' }}>从底部滑出。</div>}> <Button variant="secondary">下</Button> </Sheet> </div>, )
自定义宽度
左右方向的面板可通过 width 设置宽度,接受数字(px)或字符串。
结果
Loading...
实时编辑器
render( <div style={{ display: 'flex', gap: 12, padding: '40px 0' }}> <Sheet width={400} title="窄面板" content={<div style={{ padding: '0 16px', flex: 1 }}>宽度:400px</div>}> <Button variant="secondary">400px</Button> </Sheet> <Sheet width="80vw" title="宽面板" content={<div style={{ padding: '0 16px', flex: 1 }}>宽度:80vw</div>}> <Button variant="secondary">80vw</Button> </Sheet> </div>, )
受控模式
结果
Loading...
实时编辑器
const Demo = () => { const [open, setOpen] = useState(false) return ( <div style={{ display: 'flex', gap: 12, alignItems: 'center', padding: '40px 0' }}> <Button onClick={() => setOpen(true)}>打开受控面板</Button> <span style={{ fontSize: 14, color: '#999' }}>open: {String(open)}</span> <Sheet open={open} onOpenChange={setOpen} title="受控面板" content={ <div style={{ padding: '0 16px', flex: 1 }}> <p>此面板由外部状态控制。</p> <Button variant="secondary" onClick={() => setOpen(false)}>从内部关闭</Button> </div> } /> </div> ) } render(<Demo />)
命令式 API
Sheet.open() 提供命令式调用,适合异步回调、快捷键、表格 action 等非 JSX trigger 场景。需要在应用根部挂载 DesignProvider 或 OverlayHost。
import { Sheet } from '@plaud/design'
Sheet.open({
title: '编辑资料',
content: ({ close }) => (
<div>
<p>内容区域。</p>
<Button onClick={close}>关闭</Button>
</div>
),
})
更新已打开的面板
open() 返回控制器,可在打开后更新配置:
const controller = Sheet.open({
title: '加载中...',
content: <div>请稍候。</div>,
})
setTimeout(() => {
controller.update({
title: '完成',
content: <div>数据已加载。</div>,
})
}, 1000)
控制器
interface ImperativeOverlayController<TOptions> {
id: string
close: () => void
update: (updater: Partial<TOptions> | ((prev: TOptions) => TOptions)) => void
afterClosed: Promise<void>
}
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
title | ReactNode | — | 标题 |
content | ReactNode | — | 主体内容 |
footer | ReactNode | — | 底部区域 |
children | ReactNode | — | 触发器(非受控模式) |
open | boolean | — | 受控打开状态 |
onOpenChange | (open: boolean) => void | — | 打开状态变更回调 |
side | 'top' | 'right' | 'bottom' | 'left' | 'right' | 滑出方向 |
width | number | string | 560 | 左右方向内容宽度(px 或 CSS 值) |
showClose | boolean | true | 是否显示关闭按钮 |
destroyOnClose | boolean | true | 关闭后是否销毁内容 |
contentClassName | string | — | 内容区域自定义 class |
使用约束
- 左右方向默认宽度 560px。
- 命令式 API 需要在应用根部挂载
DesignProvider或OverlayHost。