import { Dialog, Button } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogWithActionsDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>删除</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
模态框标题
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="text-lark-subtle">
这是一段示例正文,用于展示对话框中的文字排版效果。
</Dialog.Description>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Dialog.Close
render={(props) => (
<Button variant="destructive" {...props}>
删除
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}安装
统一导出
import { Dialog } from "@lark-ui/core";按需导出
import { Dialog } from "@lark-ui/core/components/dialog";用法
import { Dialog, Button } from "@lark-ui/core";
export default function Example() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>Open</Button>} />
<Dialog>
<Dialog.Title>Dialog Title</Dialog.Title>
<Dialog.Description>Dialog content goes here.</Dialog.Description>
<div className="flex justify-end gap-2 mt-4">
<Dialog.Close
render={(p) => (
<Button variant="secondary" {...p}>
Cancel
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}Dialog 与 Alert Dialog 的区别
对话框(Dialog)组件支持两种 ARIA 角色,以便向辅助技术准确传达语义:
| 角色 | 使用场景 | 行为 |
|---|---|---|
| 通用弹窗、表单、内容展示 | 默认可关闭 |
role="alertdialog" | 破坏性操作、确认、关键警告 | 需要用户明确确认 |
示例
基础对话框
import { Dialog, Button } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogBasicDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>点击我</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
模态框标题
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="text-lark-subtle">
这是一段示例正文,用于展示对话框中的文字排版效果。
</Dialog.Description>
</Dialog>
</Dialog.Root>
);
}尺寸
size 属性控制对话框在桌面端的固定宽度。超出对话框宽度的内容会在对话框内部横向滚动,而不是撑宽对话框。
import { Dialog, Button } from "@lark-ui/core";
import { DialogProps } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
/**
* 演示每种对话框尺寸都会保持固定宽度,不受内容影响。
* 每个对话框都包含一张宽表格,之前会导致对话框被拉伸到超出预期尺寸。
*/
export function DialogSizesDemo() {
const sizes: {
size: NonNullable<DialogProps["size"]>;
label: string;
width: string;
}[] = [
{ size: "sm", label: "小", width: "288px" },
{ size: "base", label: "基础", width: "384px" },
{ size: "lg", label: "大", width: "512px" },
{ size: "xl", label: "特大", width: "768px" },
];
return (
<div className="flex flex-wrap gap-2">
{sizes.map(({ size, label, width }) => (
<Dialog.Root key={size}>
<Dialog.Trigger
render={(p) => (
<Button variant="secondary" {...p}>
{label} ({width})
</Button>
)}
/>
<Dialog size={size} className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
{label} 对话框
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="text-lark-subtle">
此 <code>size="{size}"</code> 对话框宽度应始终保持 {width}。
</Dialog.Description>
<div className="mt-4 overflow-auto rounded-md border border-lark-line">
<table className="w-max text-sm">
<thead className="bg-lark-elevated text-left">
<tr>
<th className="px-3 py-2">资源</th>
<th className="px-3 py-2">区域</th>
<th className="px-3 py-2">状态</th>
<th className="px-3 py-2">延迟</th>
<th className="px-3 py-2">请求数</th>
<th className="px-3 py-2">最后部署时间</th>
</tr>
</thead>
<tbody className="divide-y divide-lark-hairline">
<tr>
<td className="px-3 py-2">api-gateway-prod</td>
<td className="px-3 py-2">us-east-1</td>
<td className="px-3 py-2 text-lark-success">健康</td>
<td className="px-3 py-2">12ms</td>
<td className="px-3 py-2">1,234,567</td>
<td className="px-3 py-2">2026-06-23</td>
</tr>
<tr>
<td className="px-3 py-2">worker-analytics</td>
<td className="px-3 py-2">eu-west-1</td>
<td className="px-3 py-2 text-lark-warning">降级</td>
<td className="px-3 py-2">89ms</td>
<td className="px-3 py-2">456,789</td>
<td className="px-3 py-2">2026-06-22</td>
</tr>
</tbody>
</table>
</div>
<div className="mt-6 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
关闭
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
))}
</div>
);
}警告对话框(role="alertdialog")
对于破坏性操作或确认类对话框,请在 Dialog.Root 上使用 role="alertdialog"。这样对话框会以 role="alertdialog" 而不是 role="dialog" 渲染,提供正确的无障碍语义。
何时使用 role="alertdialog":
- 破坏性操作(删除、丢弃、移除)
- 需要用户明确确认的确认流程
- 无法撤销的操作
- 关键警告或错误
import { Dialog, Button } from "@lark-ui/core";
import { Warning } from "@phosphor-icons/react";
/**
* 用于破坏性操作的警示对话框,使用 role="alertdialog"。
* 这为确认流程提供了正确的无障碍语义。
*/
export function DialogAlertDemo() {
return (
<Dialog.Root role="alertdialog">
<Dialog.Trigger
render={(p) => (
<Button {...p} variant="destructive">
删除账户
</Button>
)}
/>
<Dialog className="p-8">
<div className="mb-4 flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-lark-danger/20">
<Warning size={20} className="text-lark-danger" weight="fill" />
</div>
<Dialog.Title className="text-xl font-semibold">
删除账户?
</Dialog.Title>
</div>
<Dialog.Description className="text-lark-subtle">
你的所有数据将从我们的服务器上永久删除。确定要继续吗?
</Dialog.Description>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Dialog.Close
render={(props) => (
<Button variant="destructive" {...props}>
删除账户
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}确认对话框(配合 disablePointerDismissal)
对于不希望点击外部即可关闭的确认对话框,请在 Dialog.Root 上使用 disablePointerDismissal。它可以与 role="alertdialog" 结合使用,以获得正确的无障碍效果。
import { Dialog, Button } from "@lark-ui/core";
import { Warning } from "@phosphor-icons/react";
export function DialogConfirmationDemo() {
return (
<Dialog.Root disablePointerDismissal>
<Dialog.Trigger
render={(p) => (
<Button {...p} variant="destructive">
删除项目
</Button>
)}
/>
<Dialog className="p-8">
<div className="mb-4 flex items-center gap-3">
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-lark-danger/20">
<Warning size={20} className="text-lark-danger" />
</div>
<Dialog.Title className="text-xl font-semibold">
删除项目?
</Dialog.Title>
</div>
<Dialog.Description className="text-lark-subtle">
此操作无法撤销,将永久删除该项目及其所有关联数据。
</Dialog.Description>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Dialog.Close
render={(props) => (
<Button variant="destructive" {...props}>
删除
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}带操作按钮
import { Dialog, Button } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogWithActionsDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>删除</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
模态框标题
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="text-lark-subtle">
这是一段示例正文,用于展示对话框中的文字排版效果。
</Dialog.Description>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Dialog.Close
render={(props) => (
<Button variant="destructive" {...props}>
删除
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}自定义最大宽度
使用方设置的最大宽度工具类(如 max-w-lg)应在桌面端限制对话框宽度,即使对话框内部包含宽度较大的内容。
import { Dialog, Button } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
/**
* 使用方提供最大宽度的对话框,内容本身较宽。
* 在桌面端面板宽度应始终不超过 max-w-lg。
*/
export function DialogMaxWidthDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>打开限宽对话框</Button>} />
<Dialog className="max-w-lg p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
覆盖最大宽度
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="text-lark-subtle">
此对话框使用 <code>className="max-w-lg"</code>,桌面端宽度应保持在
512px 左右。
</Dialog.Description>
<div className="mt-4 truncate rounded-md border border-lark-line bg-lark-recessed p-3 font-mono text-sm">
abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
</div>
</Dialog>
</Dialog.Root>
);
}搭配 Select 使用
包含 Select 下拉选择器的对话框。
import { Dialog, Button, Select } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogWithSelectDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>打开表单</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
创建资源
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="mb-4 text-lark-subtle">
为你的新资源选择一个区域。
</Dialog.Description>
<Select
className="w-full"
placeholder="选择区域…"
renderValue={(v) => regions.find((r) => r.value === v)?.label}
>
{regions.map((region) => (
<Select.Option key={region.value} value={region.value}>
{region.label}
</Select.Option>
))}
</Select>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Button variant="primary">创建</Button>
</div>
</Dialog>
</Dialog.Root>
);
}搭配 Combobox 使用
包含 Combobox 组合框(支持搜索选择)的对话框。
import { useState } from "react";
import { Dialog, Button, Combobox } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogWithComboboxDemo() {
const [value, setValue] = useState<{ value: string; label: string } | null>(
null,
);
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>打开表单</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
创建资源
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="mb-4 text-lark-subtle">
搜索并为你的新资源选择一个区域。
</Dialog.Description>
<Combobox value={value} onValueChange={setValue} items={regions}>
<Combobox.TriggerInput className="w-full" placeholder="搜索区域…" />
<Combobox.Content>
<Combobox.Empty>未找到区域</Combobox.Empty>
<Combobox.List>
{(item: { value: string; label: string }) => (
<Combobox.Item key={item.value} value={item}>
{item.label}
</Combobox.Item>
)}
</Combobox.List>
</Combobox.Content>
</Combobox>
<div className="mt-8 flex justify-end gap-2">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
取消
</Button>
)}
/>
<Button variant="primary">创建</Button>
</div>
</Dialog>
</Dialog.Root>
);
}搭配 Dropdown 使用
包含 Dropdown 下拉菜单的对话框。
import { Dialog, Button, DropdownMenu } from "@lark-ui/core";
import { X } from "@phosphor-icons/react";
export function DialogWithDropdownDemo() {
return (
<Dialog.Root>
<Dialog.Trigger render={(p) => <Button {...p}>打开表单</Button>} />
<Dialog className="p-8">
<div className="mb-4 flex items-start justify-between gap-4">
<Dialog.Title className="text-2xl font-semibold">
资源操作
</Dialog.Title>
<Dialog.Close
aria-label="关闭"
render={(props) => (
<Button
{...props}
variant="secondary"
shape="square"
icon={<X />}
aria-label="关闭"
/>
)}
/>
</div>
<Dialog.Description className="mb-4 text-lark-subtle">
为选中的资源选择一项操作。
</Dialog.Description>
<DropdownMenu>
<DropdownMenu.Trigger render={<Button>操作</Button>} />
<DropdownMenu.Content>
<DropdownMenu.Item>编辑</DropdownMenu.Item>
<DropdownMenu.Item>创建副本</DropdownMenu.Item>
<DropdownMenu.Separator />
<DropdownMenu.Item variant="danger">删除</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu>
<div className="mt-8 flex justify-end">
<Dialog.Close
render={(props) => (
<Button variant="secondary" {...props}>
关闭
</Button>
)}
/>
</div>
</Dialog>
</Dialog.Root>
);
}API 参考
Dialog
主对话框容器,负责渲染模态遮罩和弹层。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| className | string | - | 通过 `cn()` 合并的额外 CSS 类名。 |
| children | ReactNode | - | 对话框内容(通常是 Title、Description、Close 和操作按钮)。 |
| container | PortalContainer | - | 传送层的容器元素。可用于把对话框渲染到 Shadow DOM 或自定义容器内。会覆盖 `LarkPortalProvider` 上下文。 |
| size | "base" | "sm" | "lg" | "xl" | "base" | 对话框宽度。 - `"sm"` — 小尺寸(288px),用于简单确认 - `"base"` — 默认(384px) - `"lg"` — 大尺寸(512px),用于复杂内容 - `"xl"` — 超大尺寸(768px),用于详情视图 |
Dialog.Root
控制对话框的打开状态。自身不渲染任何 HTML 元素。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| role | ”dialog” | “alertdialog" | "dialog” | 对话框的 ARIA 角色。破坏性操作或确认流程请使用 |
| disablePointerDismissal | boolean | false | 为 true 时,防止通过点击对话框外部将其关闭。 |
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。
Dialog.Trigger
点击时打开对话框的按钮。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。
Dialog.Title
为对话框提供无障碍标签的标题。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。
Dialog.Description
为对话框提供补充说明的段落。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。
Dialog.Close
点击时关闭对话框的按钮。
| 属性 | 类型 | 默认值 |
|---|
该组件没有专有属性,支持标准 HTML 属性。