feat: stash-ui 0.1.0(40 个组件 + 文档站 + 主题机制)
This commit is contained in:
@@ -0,0 +1,120 @@
|
||||
import { useState } from 'react'
|
||||
import { Button, Modal, Notice, Space } from '../../src'
|
||||
import { Demo } from '../components/Demo'
|
||||
import { PropsTable } from '../components/PropsTable'
|
||||
import { Section } from '../components/Section'
|
||||
|
||||
export function Modals() {
|
||||
const [confirmOpen, setConfirmOpen] = useState(false)
|
||||
const [infoOpen, setInfoOpen] = useState(false)
|
||||
const [deleted, setDeleted] = useState(false)
|
||||
|
||||
return (
|
||||
<Section
|
||||
id="modal"
|
||||
title="弹窗"
|
||||
api="Modal"
|
||||
desc="基于原生 <dialog>:焦点陷阱、Esc 关闭、背景 inert 由浏览器提供,组件补样式、滚动锁和受控开关。对应参考站的 .nice-tips(遮罩 60% 黑、内容 12px 圆角、上滑淡入)。"
|
||||
>
|
||||
<Demo
|
||||
title="确认弹窗"
|
||||
desc="危险操作要二次确认;确认后由调用方关闭并把结果反馈给页面(这里用 Notice 示意)。"
|
||||
layout="column"
|
||||
code={`const [open, setOpen] = useState(false)
|
||||
|
||||
<Modal
|
||||
open={open}
|
||||
onClose={() => setOpen(false)}
|
||||
title="删除这篇内容?"
|
||||
footer={
|
||||
<>
|
||||
<Button variant="ghost" onClick={() => setOpen(false)}>取消</Button>
|
||||
<Button variant="danger" onClick={handleDelete}>删除</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
删除后不可恢复,占位数据会被一起清掉。
|
||||
</Modal>`}
|
||||
>
|
||||
<Space gap="md" wrap>
|
||||
<Button variant="danger" onClick={() => setConfirmOpen(true)}>
|
||||
删除内容
|
||||
</Button>
|
||||
<Button variant="secondary" onClick={() => setInfoOpen(true)}>
|
||||
打开说明弹窗
|
||||
</Button>
|
||||
</Space>
|
||||
|
||||
{deleted && (
|
||||
<Notice title="示例:已删除" action={{ label: '撤销', onClick: () => setDeleted(false) }}>
|
||||
这里只是演示确认流程,没有真的删数据。
|
||||
</Notice>
|
||||
)}
|
||||
</Demo>
|
||||
|
||||
<Demo
|
||||
title="尺寸与长内容"
|
||||
desc="sm 300 / md 460 / lg 640;内容多时弹窗内部不滚动、由页面决定(这里演示 lg 的排版)。"
|
||||
layout="column"
|
||||
code={`<Modal size="lg" title="关于这套组件" open={open} onClose={close}>…</Modal>`}
|
||||
>
|
||||
<Button variant="secondary" onClick={() => setInfoOpen(true)}>
|
||||
打开 lg 弹窗
|
||||
</Button>
|
||||
</Demo>
|
||||
|
||||
<PropsTable
|
||||
rows={[
|
||||
{ name: 'open', type: 'boolean', required: true, desc: '受控开关' },
|
||||
{ name: 'onClose', type: '() => void', required: true, desc: 'Esc / 遮罩 / 关闭按钮都会调用' },
|
||||
{ name: 'title', type: 'ReactNode', required: true, desc: '标题,同时作为 aria-labelledby' },
|
||||
{ name: 'children', type: 'ReactNode', desc: '正文' },
|
||||
{ name: 'footer', type: 'ReactNode', desc: '底部操作区(通常放按钮)' },
|
||||
{ name: 'size', type: "'sm' | 'md' | 'lg'", defaultValue: "'md'", desc: '300 / 460 / 640' },
|
||||
{ name: 'closeOnOverlay', type: 'boolean', defaultValue: 'true', desc: '点遮罩是否关闭' },
|
||||
]}
|
||||
/>
|
||||
|
||||
<Modal
|
||||
open={confirmOpen}
|
||||
onClose={() => setConfirmOpen(false)}
|
||||
title="删除这篇内容?"
|
||||
footer={
|
||||
<>
|
||||
<Button variant="ghost" onClick={() => setConfirmOpen(false)}>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
variant="danger"
|
||||
onClick={() => {
|
||||
setConfirmOpen(false)
|
||||
setDeleted(true)
|
||||
}}
|
||||
>
|
||||
删除
|
||||
</Button>
|
||||
</>
|
||||
}
|
||||
>
|
||||
删除后不可恢复,占位数据会被一起清掉。
|
||||
</Modal>
|
||||
|
||||
<Modal
|
||||
open={infoOpen}
|
||||
onClose={() => setInfoOpen(false)}
|
||||
title="关于这套组件"
|
||||
size="lg"
|
||||
footer={
|
||||
<Button onClick={() => setInfoOpen(false)}>知道了</Button>
|
||||
}
|
||||
>
|
||||
<p>
|
||||
组件只依赖令牌,不依赖任何业务数据;页面用 Card / Grid / Space 组合,弹窗只负责「打断」。
|
||||
</p>
|
||||
<p style={{ marginTop: 12 }}>
|
||||
关闭方式有三种:右上角按钮、Esc、点击遮罩。打开时背景滚动会被锁住,关闭后恢复。
|
||||
</p>
|
||||
</Modal>
|
||||
</Section>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user