feat(overlays): add managed overlay package
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
---
|
||||
title: 安装与基础交互
|
||||
description: 按需挂载原子 Host,并使用全局或局部 Scope 打开浮层。
|
||||
order: 10
|
||||
toc:
|
||||
- id: atomic-hosts
|
||||
title: 原子 Host
|
||||
- id: global-scope
|
||||
title: 默认全局 Scope
|
||||
- id: local-scopes
|
||||
title: 局部和命名局部
|
||||
- id: message-overlays
|
||||
title: 消息类浮层
|
||||
- id: toast
|
||||
title: Toast
|
||||
---
|
||||
|
||||
## 原子 Host {#atomic-hosts}
|
||||
|
||||
在应用样式入口导入 Tailwind source:
|
||||
|
||||
```css
|
||||
@import "@workspace/overlays/globals.css";
|
||||
```
|
||||
|
||||
只挂载应用实际使用的 Host。下面的应用不会引入 Sheet、Drawer 或 Toast:
|
||||
|
||||
```tsx
|
||||
import { AlertHost } from "@workspace/overlays/alert"
|
||||
import { ConfirmHost } from "@workspace/overlays/confirm"
|
||||
import { ModalHost } from "@workspace/overlays/modal"
|
||||
|
||||
export function Root({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<>
|
||||
{children}
|
||||
<AlertHost />
|
||||
<ConfirmHost />
|
||||
<ModalHost />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
确定会使用全部能力的应用也可以从 `@workspace/overlays/all` 导入便捷的 `OverlayHost`。它会主动引入所有 feature,因此不是默认推荐方式。
|
||||
|
||||
## 默认全局 Scope {#global-scope}
|
||||
|
||||
`openXxx()` 和没有 `scope` prop 的 Host 默认使用 `globalOverlayScope`。调用方不需要 React Context:
|
||||
|
||||
```tsx
|
||||
import { openAlert } from "@workspace/overlays/alert"
|
||||
|
||||
await openAlert({
|
||||
title: "导出完成",
|
||||
description: "文件已经可以下载。",
|
||||
})
|
||||
```
|
||||
|
||||
应用仍需挂载对应的 `AlertHost`。打开请求可以发生在 Host 挂载之前,Base UI handle 会在 Host 出现后渲染它。
|
||||
|
||||
## 局部和命名局部 {#local-scopes}
|
||||
|
||||
Scope 是实际对象,不使用全局字符串注册表:
|
||||
|
||||
```tsx
|
||||
import {
|
||||
createOverlayScope,
|
||||
OverlayScopeProvider,
|
||||
useOverlayScope,
|
||||
} from "@workspace/overlays"
|
||||
import { ModalHost, openModal } from "@workspace/overlays/modal"
|
||||
|
||||
const editorScope = createOverlayScope({ name: "editor" })
|
||||
const pickerScope = createOverlayScope({ name: "picker" })
|
||||
|
||||
function EditorRoot({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<OverlayScopeProvider scope={editorScope} scopes={{ picker: pickerScope }}>
|
||||
{children}
|
||||
<ModalHost />
|
||||
<ModalHost scope={pickerScope} />
|
||||
</OverlayScopeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function OpenPickerButton() {
|
||||
const scope = useOverlayScope("picker")
|
||||
return (
|
||||
<button
|
||||
onClick={() =>
|
||||
openModal({ scope, title: "选择资源", content: <AssetPicker /> })
|
||||
}
|
||||
>
|
||||
选择资源
|
||||
</button>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
`<OverlayScopeProvider name="editor">` 可以自动创建一个局部 Scope。非 React 模块应保存并显式传递 `createOverlayScope()` 返回的对象。
|
||||
|
||||
## 消息类浮层 {#message-overlays}
|
||||
|
||||
```tsx
|
||||
import { openConfirm } from "@workspace/overlays/confirm"
|
||||
|
||||
async function removeProject() {
|
||||
const accepted = await openConfirm({
|
||||
title: "删除项目?",
|
||||
description: "此操作无法撤销。",
|
||||
destructive: true,
|
||||
})
|
||||
|
||||
if (accepted) await deleteProject()
|
||||
}
|
||||
```
|
||||
|
||||
`openAlert()` 返回 `Promise<void>`;`openConfirm()` 返回布尔值;`openPrompt()` 返回字符串,并在取消时返回 `null`。
|
||||
|
||||
## Toast {#toast}
|
||||
|
||||
```tsx
|
||||
import { dismissToast, openToast, updateToast } from "@workspace/overlays/toast"
|
||||
|
||||
const id = openToast({
|
||||
title: "保存成功",
|
||||
description: "修改已经同步。",
|
||||
type: "success",
|
||||
})
|
||||
|
||||
updateToast(id, { description: "所有设备均已同步。" })
|
||||
dismissToast({ id })
|
||||
```
|
||||
|
||||
Toast 同样按 Scope 隔离,并由对应的 `ToastHost` 渲染。
|
||||
Reference in New Issue
Block a user