组件

对话框

一个覆盖在主窗口或其他对话框窗口上的窗口,使下面的内容处于非活动状态。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
import { Cross2Icon } from '@radix-ui/react-icons';
import './styles.css';
const DialogDemo = () => (
<Dialog.Root>
<Dialog.Trigger asChild>
<button className="Button violet">Edit profile</button>
</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="DialogOverlay" />
<Dialog.Content className="DialogContent">
<Dialog.Title className="DialogTitle">Edit profile</Dialog.Title>
<Dialog.Description className="DialogDescription">
Make changes to your profile here. Click save when you're done.
</Dialog.Description>
<fieldset className="Fieldset">
<label className="Label" htmlFor="name">
Name
</label>
<input className="Input" id="name" defaultValue="Pedro Duarte" />
</fieldset>
<fieldset className="Fieldset">
<label className="Label" htmlFor="username">
Username
</label>
<input className="Input" id="username" defaultValue="@peduarte" />
</fieldset>
<div style={{ display: 'flex', marginTop: 25, justifyContent: 'flex-end' }}>
<Dialog.Close asChild>
<button className="Button green">Save changes</button>
</Dialog.Close>
</div>
<Dialog.Close asChild>
<button className="IconButton" aria-label="Close">
<Cross2Icon />
</button>
</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
export default DialogDemo;

功能

    支持模态和非模态模式。

    模态时自动捕获焦点。

    可以是受控或不受控的。

    使用Title Description组件管理屏幕阅读器公告。

    Esc 自动关闭组件。

安装

从命令行安装组件。

npm install @radix-ui/react-dialog

结构

导入所有部分并将其组合在一起。

import * as Dialog from '@radix-ui/react-dialog';
export default () => (
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<Dialog.Title />
<Dialog.Description />
<Dialog.Close />
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);

API 参考

包含对话框的所有部分。

属性类型默认值
defaultOpen
布尔值
无默认值
open
布尔值
无默认值
onOpenChange
函数
无默认值
modal
布尔值
true

触发器

打开对话框的按钮。

属性类型默认值
asChild
布尔值
false
数据属性
[data-state]"open" |"closed"

传送门

使用时,将覆盖层和内容部分传送至body

属性类型默认值
forceMount
布尔值
无默认值
容器
HTMLElement
document.body

覆盖层

对话框打开时覆盖视图非活动部分的层。

属性类型默认值
asChild
布尔值
false
forceMount
布尔值
无默认值
数据属性
[data-state]"open" |"closed"

内容

包含要在打开的对话框中渲染的内容。

属性类型默认值
asChild
布尔值
false
forceMount
布尔值
无默认值
onOpenAutoFocus
函数
无默认值
onCloseAutoFocus
函数
无默认值
onEscapeKeyDown
函数
无默认值
onPointerDownOutside
函数
无默认值
onInteractOutside
函数
无默认值
数据属性
[data-state]"open" |"closed"

关闭

关闭对话框的按钮。

属性类型默认值
asChild
布尔值
false

标题

对话框打开时要宣布的可访问标题。

如果要隐藏标题,请将其包装在我们的视觉隐藏实用程序中,如下所示<VisuallyHidden asChild>

属性类型默认值
asChild
布尔值
false

描述

对话框打开时要宣布的可选可访问描述。

如果要隐藏描述,请将其包装在我们的视觉隐藏实用程序中,如下所示<VisuallyHidden asChild>。如果要完全删除描述,请删除此部分并将aria-describedby={undefined}传递给Dialog.Content

属性类型默认值
asChild
布尔值
false

示例

异步表单提交后关闭

使用受控属性在异步操作完成后以编程方式关闭 Dialog。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
const wait = () => new Promise((resolve) => setTimeout(resolve, 1000));
export default () => {
const [open, setOpen] = React.useState(false);
return (
<Dialog.Root open={open} onOpenChange={setOpen}>
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
<form onSubmit={(event) => { wait().then(() => setOpen(false)); event.preventDefault(); }} >
{/** some inputs */}
<button type="submit">Submit</button>
</form>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
);
};

可滚动覆盖层

将内容移到覆盖层内以渲染具有溢出的对话框。

// index.jsx
import * as Dialog from '@radix-ui/react-dialog';
import './styles.css';
export default () => {
return (
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal>
<Dialog.Overlay className="DialogOverlay">
<Dialog.Content className="DialogContent">...</Dialog.Content>
</Dialog.Overlay>
</Dialog.Portal>
</Dialog.Root>
);
};
/* styles.css */
.DialogOverlay {
background: rgba(0 0 0 / 0.5);
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
display: grid;
place-items: center;
overflow-y: auto;
}
.DialogContent {
min-width: 300px;
background: white;
padding: 30px;
border-radius: 4px;
}

自定义传送门容器

自定义对话框弹出的元素。

import React from 'react';
import * as Dialog from '@radix-ui/react-dialog';
export default () => {
const [container, setContainer] = React.useState(null);
return (
<div>
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Portal container={container}>
<Dialog.Overlay />
<Dialog.Content>...</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
<div ref={setContainer} />
</div>
);
};

可访问性

遵循对话框 WAI-ARIA 设计模式

键盘交互

描述
空格
打开/关闭对话框。
回车
打开/关闭对话框。
Tab
将焦点移动到下一个可聚焦元素。
Shift + Tab
将焦点移动到上一个可聚焦元素。
Esc
关闭对话框并将焦点移动到Dialog.Trigger

自定义 API

通过将基本部分抽象到您自己的组件中来创建您自己的 API。

抽象覆盖层和关闭按钮

此示例抽象了Dialog.OverlayDialog.Close 部分。

用法

import { Dialog, DialogTrigger, DialogContent } from './your-dialog';
export default () => (
<Dialog>
<DialogTrigger>Dialog trigger</DialogTrigger>
<DialogContent>Dialog Content</DialogContent>
</Dialog>
);

实现

// your-dialog.jsx
import React from 'react';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { Cross1Icon } from '@radix-ui/react-icons';
export const DialogContent = React.forwardRef(
({ children, ...props }, forwardedRef) => (
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay />
<DialogPrimitive.Content {...props} ref={forwardedRef}>
{children}
<DialogPrimitive.Close aria-label="Close">
<Cross1Icon />
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
)
);
export const Dialog = DialogPrimitive.Root;
export const DialogTrigger = DialogPrimitive.Trigger;
下一页下拉菜单