import { useState } from "react";
import { Button, Input, LayerDialog } from "@cloudflare/kumo";
export function LayerDialogActionDemo() {
const [name, setName] = useState("Production API");
const [hostname, setHostname] = useState("api.example.com");
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open settings</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Configure custom hostname</LayerDialog.Title>
<LayerDialog.Description>
Route requests for this hostname to your Worker.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-5">
<Input
label="Hostname"
onChange={(event) => setHostname(event.target.value)}
value={hostname}
/>
<Input
label="Display name"
onChange={(event) => setName(event.target.value)}
value={name}
/>
</div>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
disabled={!hostname || !name}
onClick={() => undefined}
>
Save hostname
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}安装
批量导入
import { LayerDialog } from "@cloudflare/kumo";细粒度导入
import { LayerDialog } from "@cloudflare/kumo/components/layer-dialog";用法
import { Button, LayerDialog } from "@cloudflare/kumo";
export default function Example() {
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open settings</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Configure custom hostname</LayerDialog.Title>
<LayerDialog.Description>
Route requests for this hostname to your Worker.
</LayerDialog.Description>
<LayerDialog.Body>{/* form fields */}</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action onClick={save}>
Save hostname
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}组合规则
LayerDialog.Content 只接受恰好一个 Title、一个 Body,以及可选的 Description 和可选的 Actions。它会自动选择关闭方式:- 没有
Actions:在标题栏中显示一个 X,且没有页脚。 - 有
Actions:去掉 X,显示 Close 或 Cancel 加一个主操作。在移动端,它们以一条细线分隔显示在滚动主体下方;在桌面端,它们固定在页脚中。
使用方不能混用这两种布局,也不能添加无关的页脚控件。Actions 只接受一个 Action,该 Action 可以通过可选方式暴露相关菜单项。只读内容用 X;需要用户提交变更时用 Actions;破坏性或关键确认则用 LayerDialog.Alert。
Description 直接渲染在吸顶标题栏内的标题下方,并成为对话框的无障碍描述。没有 Description 时,由正文文案来描述该对话框。
信息提示对话框
Title 和 Description 始终位于带边框的主体表面上。标题栏在正文滚动时保持可见,并独占自动的 X 关闭操作。当正文滚过顶部后,描述会折叠到标题下方,为内容腾出更多空间;回到顶部时又会重新展开。内容边缘的遮罩提示已溢出。import { Button, LayerDialog, Text } from "@cloudflare/kumo";
function LongContent() {
return (
<div className="flex flex-col gap-5">
<div className="rounded-lg border border-kumo-line p-4 text-kumo-subtle">
Navigation and command shortcuts
</div>
<Text variant="secondary">
The title frame stays visible, receives a divider once content scrolls,
and the scroll mask indicates more content below.
</Text>
<div className="h-96" />
</div>
);
}
export function LayerDialogInformationalDemo() {
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open keyboard shortcuts</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Keyboard shortcuts</LayerDialog.Title>
<LayerDialog.Description>
Browse available shortcuts without changing a setting.
</LayerDialog.Description>
<LayerDialog.Body>
<LongContent />
</LayerDialog.Body>
</LayerDialog.Content>
</LayerDialog.Root>
);
}标准操作
添加Actions 会恰好选定一个 Kumo 主操作,并自动生成一个 Close 按钮。在移动端,操作以一条细线分隔显示在滚动主体下方;在桌面端,它们占据固定的页脚。使用方不能添加无关的页脚控件或额外的行动号召 (CTA)。主操作接受 variant="primary"(默认) 或 variant="destructive"。import { useState } from "react";
import { Button, Input, LayerDialog } from "@cloudflare/kumo";
export function LayerDialogActionDemo() {
const [name, setName] = useState("Production API");
const [hostname, setHostname] = useState("api.example.com");
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open settings</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Configure custom hostname</LayerDialog.Title>
<LayerDialog.Description>
Route requests for this hostname to your Worker.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-5">
<Input
label="Hostname"
onChange={(event) => setHostname(event.target.value)}
value={hostname}
/>
<Input
label="Display name"
onChange={(event) => setName(event.target.value)}
value={name}
/>
</div>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
disabled={!hostname || !name}
onClick={() => undefined}
>
Save hostname
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}原生表单
Body 和 Actions 是彼此独立的插槽,因此原生 <form> 应放在 Body 内,而它的提交按钮应放在 Actions 中。给表单一个 ID,再通过主操作的 HTML form 属性与之关联。这样可以保留内置校验,并在不使用 React 状态的情况下支持非受控表单字段。
import { useId } from "react";
import { Button, Input, LayerDialog } from "@cloudflare/kumo";
export function LayerDialogFormDemo() {
const formId = useId();
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Create deployment</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Create deployment</LayerDialog.Title>
<LayerDialog.Description>
The browser owns the form’s native validation and submission state.
</LayerDialog.Description>
<LayerDialog.Body>
<form
id={formId}
className="flex flex-col gap-5"
onSubmit={(event) => event.preventDefault()}
>
<Input
label="Service name"
name="serviceName"
placeholder="production-api"
required
/>
<Input
label="Compatibility date"
name="compatibilityDate"
required
type="date"
/>
</form>
</LayerDialog.Body>
<LayerDialog.Actions dismissLabel="Cancel">
<LayerDialog.Action form={formId} type="submit">
Create deployment
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}搜索与选择器
某个控件可以作为 Body 中的第一个元素。这里的无标签搜索输入框直接位于标题栏下方,因此要给它一个 aria-label。主体在其内容上方留有空间,所以输入框的边框和焦点环不会被滚动区域裁剪。
import { useState } from "react";
import { Button, Input, LayerDialog, Text } from "@cloudflare/kumo";
/** Unlabeled search input as the first control in the body. */
export function LayerDialogSearchDemo() {
const [query, setQuery] = useState("");
const matches = WORKERS.filter((worker) =>
worker.toLowerCase().includes(query.trim().toLowerCase()),
);
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Choose a Worker</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Choose a Worker</LayerDialog.Title>
<LayerDialog.Description>
Select the Worker that handles requests for this route.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-3">
<Input
aria-label="Search Workers"
onChange={(event) => setQuery(event.target.value)}
placeholder="Search Workers"
type="search"
value={query}
/>
{matches.length > 0 ? (
<ul className="flex flex-col divide-y divide-kumo-hairline rounded-lg border border-kumo-hairline">
{matches.map((worker) => (
<li key={worker} className="px-3 py-2 text-kumo-default">
{worker}
</li>
))}
</ul>
) : (
<Text variant="secondary">No Workers match “{query}”.</Text>
)}
</div>
</LayerDialog.Body>
</LayerDialog.Content>
</LayerDialog.Root>
);
}多个主操作
通过 LayerDialog.Action 的 menu 属性传入相关操作。它会在操作旁渲染一个标准化的分段按钮箭头。自动关闭按钮要与之分开。例如,Save and deploy 可以通过菜单暴露 Save as draft,而不会把页脚变成三个同级操作。
import { Button, DropdownMenu, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogSplitActionDemo() {
return (
<div className="flex flex-wrap justify-center gap-3">
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Edit deployment</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Save deployment</LayerDialog.Title>
<LayerDialog.Description>
Deploy these changes now, or keep them as a draft.
</LayerDialog.Description>
<LayerDialog.Body>
<Text variant="secondary">
The alternate save outcome is related to the primary action, so it
lives in its split-button menu rather than as an unrelated footer
button.
</Text>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
menu={[
<DropdownMenu.Item key="draft">
Save as draft
</DropdownMenu.Item>,
]}
menuLabel="Save options"
>
Save and deploy
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
<LayerDialog.Alert>
<LayerDialog.Trigger
render={(props) => (
<Button {...props} variant="secondary">
Delete deployment
</Button>
)}
/>
<LayerDialog.Content>
<LayerDialog.Title>Delete deployment</LayerDialog.Title>
<LayerDialog.Description>
This permanently removes the deployment and cannot be undone.
</LayerDialog.Description>
<LayerDialog.Body>
<Text variant="secondary">
The destructive split button keeps every part of the action,
including the menu trigger, visually consistent.
</Text>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
menu={[
<DropdownMenu.Item key="delete-with-tokens">
Delete and revoke tokens
</DropdownMenu.Item>,
]}
menuLabel="Delete options"
variant="destructive"
>
Delete deployment
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Alert>
</div>
);
}取消文案
当存在LayerDialog.Actions 时,LayerDialog 会渲染一个关闭按钮。它在移动端使用次级按钮样式,在桌面端页脚中使用幽灵按钮样式。其默认文案是 “Close”,对于 LayerDialog.Alert 则是 “Cancel”。只有当该对话框需要更具体的措辞 (如 “Keep editing” 或 “Discard changes”) 时才使用 dismissLabel。该文案不会改变按钮的行为:它始终关闭对话框。
import { useState } from "react";
import { Button, Input, LayerDialog } from "@cloudflare/kumo";
export function LayerDialogCancelDemo() {
const [email, setEmail] = useState("alex@example.com");
const [name, setName] = useState("Alex Morgan");
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Edit profile</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Edit profile</LayerDialog.Title>
<LayerDialog.Description>
Update the profile information shown to your teammates. Changes are
not saved until you confirm.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-5">
<Input
label="Display name"
onChange={(event) => setName(event.target.value)}
value={name}
/>
<Input
label="Email address"
onChange={(event) => setEmail(event.target.value)}
type="email"
value={email}
/>
</div>
</LayerDialog.Body>
<LayerDialog.Actions dismissLabel="Cancel">
<LayerDialog.Action
disabled={!email || !name}
onClick={() => undefined}
>
Save changes
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}确认与破坏性操作
LayerDialog.Alert 遵循 Base UI 的警告对话框 (alert dialog):它提供 role="alertdialog"、自动的 Cancel、没有 X、始终是模态的,并阻止点击遮罩和滑动关闭。Escape 仍然可以取消,与 ARIA 警告对话框模式一致。
当确认操作不可逆时,给主操作传入 variant="destructive"。确认非破坏性但关键步骤的警告则保持默认的主操作样式。import { useState } from "react";
import { Button, Input, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogAlertDemo() {
const workerName = "example-worker";
const [confirmation, setConfirmation] = useState("");
return (
<LayerDialog.Alert>
<LayerDialog.Trigger
render={(props) => (
<Button variant="secondary-destructive" {...props}>
Delete Worker
</Button>
)}
/>
<LayerDialog.Content>
<LayerDialog.Title>Delete Worker</LayerDialog.Title>
<LayerDialog.Description>
Deleting{" "}
<strong className="font-medium text-kumo-default">
{workerName}
</strong>{" "}
is permanent.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-5">
<Text variant="secondary">
This deletes the Worker, deployments, and configuration. If this
Worker consumes Queues, those connections are removed first.
Queues, D1 databases, and messages stay in your account.
</Text>
<Input
label={
<>
Type{" "}
<strong className="font-medium text-kumo-default">
{workerName}
</strong>{" "}
to confirm
</>
}
onChange={(event) => setConfirmation(event.target.value)}
placeholder={workerName}
value={confirmation}
/>
</div>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
disabled={confirmation !== workerName}
onClick={() => undefined}
variant="destructive"
>
Delete Worker
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Alert>
);
}嵌套对话框
当用户必须确认一个相关操作时,可在父对话框的主体内嵌套一个LayerDialog.Root 或 LayerDialog.Alert。每个对话框各自挂载 (portal);Base UI 会让嵌套的抽屉保持在其父级之上,并在关闭时把焦点还给父级触发器。嵌套抽屉会在父级之上渲染自己的遮罩,因此父级保持完整但明显处于非活动状态。无需任何 z-index 覆盖。import { Button, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogNestedDemo() {
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Edit deployment</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Edit deployment</LayerDialog.Title>
<LayerDialog.Description>
Review the deployment settings before saving.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="flex flex-col gap-4">
<Text variant="secondary">
Opening a second dialog from this body should keep the first
dialog beneath it and restore focus when it closes.
</Text>
<LayerDialog.Alert>
<LayerDialog.Trigger
render={(props) => (
<Button variant="secondary-destructive" {...props}>
Discard changes
</Button>
)}
/>
<LayerDialog.Content size="sm">
<LayerDialog.Title>Discard unsaved changes?</LayerDialog.Title>
<LayerDialog.Description>
Your deployment edits will be permanently lost.
</LayerDialog.Description>
<LayerDialog.Body>
<Text variant="secondary">
This nested alert is independently portaled and should
dismiss back to the edit dialog.
</Text>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action variant="destructive">
Discard changes
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Alert>
</div>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action>Save changes</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}进行中的任务
异步任务进行期间,dismissDisabled 会一并阻止所有由用户发起的关闭方式。通过 actionsRef.current.close() 或受控的 open 属性进行的编程式关闭仍然有效,以便操作成功后可以关闭对话框。唯一的主操作自行管理其加载或禁用状态。import { useState } from "react";
import { Button, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogPendingDemo() {
const [pending, setPending] = useState(false);
return (
<LayerDialog.Root dismissDisabled={pending}>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Save a setting</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Save a setting</LayerDialog.Title>
<LayerDialog.Description>
While saving, Close, Escape, backdrop, and mobile swipe dismissals are
blocked together.
</LayerDialog.Description>
<LayerDialog.Body>
<Text variant="secondary">
Programmatic closes still work, so a successful save can dismiss the
dialog through `actionsRef` or a controlled `open` prop.
</Text>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action
loading={pending}
onClick={() => {
setPending(true);
window.setTimeout(() => setPending(false), 1500);
}}
>
Save changes
</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
);
}清理
把清理逻辑放在onOpenChange 中,而不是关闭按钮的点击处理器中,这样无论是 X、Close、Escape、遮罩还是滑动关闭,它都会执行。import { useState } from "react";
import { Button, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogCleanupDemo() {
const [open, setOpen] = useState(false);
const [cleanupCount, setCleanupCount] = useState(0);
return (
<LayerDialog.Root
open={open}
onOpenChange={(nextOpen) => {
if (!nextOpen) setCleanupCount((count) => count + 1);
setOpen(nextOpen);
}}
>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open draft</Button>}
/>
<LayerDialog.Content>
<LayerDialog.Title>Draft settings</LayerDialog.Title>
<LayerDialog.Body>
<Text variant="secondary">
Cleanup has run {cleanupCount} time{cleanupCount === 1 ? "" : "s"}.
</Text>
</LayerDialog.Body>
</LayerDialog.Content>
</LayerDialog.Root>
);
}本地化
对话框会渲染两处自有文案。通过 KumoLocaleProvider 配置它们的全应用默认值:
layerDialog.close用于自动的 X 按钮和默认的页脚关闭按钮。默认值:“Close”。layerDialog.cancel用于Alert内默认的页脚关闭按钮。
<KumoLocaleProvider
translations={{
layerDialog: { close: "Schließen", cancel: "Abbrechen" },
}}
>
<App />
</KumoLocaleProvider>当某个对话框需要自定义文案时,在 Content 上使用 closeLabel,或在 Actions 上使用 dismissLabel;显式传入的属性会覆盖 Provider 的默认值。
桌面端宽度
桌面端对话框默认使用size="base"(576px)。当内容需要不同宽度时,可使用 sm(448px)、lg(672px) 或 xl(768px)。移动端对话框在任何尺寸下都保持全宽。import { useState } from "react";
import { Button, Input, LayerDialog, KumoLayerDialogSize } from "@cloudflare/kumo";
export function LayerDialogSizeDemo() {
const [open, setOpen] = useState(false);
const [size, setSize] = useState<KumoLayerDialogSize>("base");
const openAtSize = (nextSize: KumoLayerDialogSize) => {
setSize(nextSize);
setOpen(true);
};
return (
<>
<div className="flex flex-wrap gap-2">
<Button onClick={() => openAtSize("sm")}>Small</Button>
<Button onClick={() => openAtSize("base")}>Default</Button>
<Button onClick={() => openAtSize("lg")}>Large</Button>
<Button onClick={() => openAtSize("xl")}>Extra large</Button>
</div>
<LayerDialog.Root open={open} onOpenChange={setOpen}>
<LayerDialog.Content size={size}>
<LayerDialog.Title>Review deployment configuration</LayerDialog.Title>
<LayerDialog.Description>
Confirm the service details and routing configuration before this
deployment is created.
</LayerDialog.Description>
<LayerDialog.Body>
<div className="grid gap-5 sm:grid-cols-2">
<Input label="Service name" defaultValue="production-api" />
<Input label="Environment" defaultValue="Production" />
<Input label="Hostname" defaultValue="api.example.com" />
<Input label="Compatibility date" defaultValue="2026-09-09" />
</div>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action>Create deployment</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
</>
);
}桌面端位置
桌面端对话框默认居中。只有当内容适合顶部对齐时,才使用窄范围的verticalAlign="top" 覆盖;移动端仍然是底部抽屉 (bottom sheet)。import { Button, LayerDialog, Text } from "@cloudflare/kumo";
export function LayerDialogTopAlignDemo() {
return (
<LayerDialog.Root>
<LayerDialog.Trigger
render={(props) => <Button {...props}>Open top-aligned dialog</Button>}
/>
<LayerDialog.Content verticalAlign="top">
<LayerDialog.Title>Top-aligned dialog</LayerDialog.Title>
<LayerDialog.Body>
<Text variant="secondary">Mobile dialogs remain bottom sheets.</Text>
</LayerDialog.Body>
</LayerDialog.Content>
</LayerDialog.Root>
);
}最大高度
高度由内容决定,并受视口限制。沿用 Base UI 的内部滚动模式,视口会为每种放置位置预留垂直呼吸空间,弹层填充该空间,因此顶部对齐的对话框绝不会超出底边。超过上限后,只有正文滚动,标题栏和操作保持固定。移动端抽屉则改为上限为视口高度的 85%。没有高度相关的属性:使用方只能通过渲染的内容来控制高度。import { useState } from "react";
import { Button, LayerDialog, KumoLayerDialogVerticalAlign } from "@cloudflare/kumo";
export function LayerDialogMaxHeightDemo() {
const [verticalAlign, setVerticalAlign] =
useState<KumoLayerDialogVerticalAlign>("center");
const [open, setOpen] = useState(false);
const openAt = (align: KumoLayerDialogVerticalAlign) => {
setVerticalAlign(align);
setOpen(true);
};
return (
<>
<div className="flex flex-wrap gap-2">
<Button onClick={() => openAt("center")}>Centered, tall content</Button>
<Button onClick={() => openAt("top")}>Top-aligned, tall content</Button>
</div>
<LayerDialog.Root open={open} onOpenChange={setOpen}>
<LayerDialog.Content verticalAlign={verticalAlign}>
<LayerDialog.Title>Audit log</LayerDialog.Title>
<LayerDialog.Description>
The dialog grows with its content until it reaches the viewport cap,
then only the body scrolls.
</LayerDialog.Description>
<LayerDialog.Body>
<ol className="flex flex-col gap-2">
{Array.from({ length: 40 }, (_, index) => (
<li
key={index}
className="rounded-lg border border-kumo-line px-3 py-2 text-kumo-subtle"
>
Entry {index + 1}
</li>
))}
</ol>
</LayerDialog.Body>
<LayerDialog.Actions>
<LayerDialog.Action>Export log</LayerDialog.Action>
</LayerDialog.Actions>
</LayerDialog.Content>
</LayerDialog.Root>
</>
);
}API 参考
LayerDialog.Root
控制打开状态。接受所有 Base UI Drawer 根属性,包括
open、defaultOpen、onOpenChange、modal 和 actionsRef。不会渲染
自己的 HTML 元素。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| dismissDisabled | boolean | false | 任务进行中时,阻止 X、Close、Escape、点击遮罩和滑动关闭。 编程式关闭永远不会被阻止。 |
LayerDialog.Alert
属性与 LayerDialog.Root 相同。强制 modal,阻止指针关闭,
渲染 role="alertdialog",并要求包含 LayerDialog.Actions。
LayerDialog.Trigger
点击时打开对话框的按钮。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专属属性,接受标准 HTML 属性。
LayerDialog.Content
挂载遮罩与弹层,并校验组合结构。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children* | ReactNode | - | - |
| container | PortalContainer | - | Container element for the portal. Overrides `KumoPortalProvider` context. |
| size | KumoLayerDialogSize | - | Desktop-only width. Mobile dialogs always remain full-width. |
| verticalAlign | KumoLayerDialogVerticalAlign | - | Desktop-only positioning. Mobile dialogs always remain bottom sheets. |
| closeLabel | string | - | Accessible name of the automatic X button. Overrides the `close` translation from KumoLocaleProvider. |
LayerDialog.Title
为无障碍标注对话框的标题。
| 属性 | 类型 | 默认值 |
|---|---|---|
| children* | ReactNode | - |
LayerDialog.Description
标题下方可选的辅助文案,会成为对话框的无障碍 描述。
| 属性 | 类型 | 默认值 |
|---|---|---|
| children* | ReactNode | - |
LayerDialog.Body
可滚动的内容区域。
| 属性 | 类型 | 默认值 |
|---|---|---|
| children* | ReactNode | - |
LayerDialog.Actions
页脚包含一个自动关闭按钮,以及恰好一个 LayerDialog.Action。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| children* | ReactNode | - | Exactly one action. Pass `menu` to LayerDialog.Action for related actions such as "Save as draft". |
| dismissLabel | string | - | Text of the automatic dismiss button. Say "Cancel" only when the workflow has a real cancel outcome. Translate it for non-English products. |
LayerDialog.Action
主操作。渲染 Kumo Button,并接受 onClick、disabled、
type 等标准按钮属性。通过 menu 传入菜单项,
可渲染配套的分段按钮菜单。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专属属性,接受标准 HTML 属性。