dialog 是一个浮动元素,它显示需要立即关注的信息,出现在页面内容上方并阻止与页面的交互,直到它被关闭。
¥A dialog is a floating element that displays information that requires immediate attention, appearing over the page content and blocking interactions with the page until it is dismissed.
它与弹出窗口具有类似的交互作用,但有两个关键区别:
¥It has similar interactions to a popover but with two key differences:
-
它是模态的,在对话框后面渲染一个背景,使其后面的内容变暗,从而使页面的其余部分无法访问。
¥It is modal and renders a backdrop behind the dialog that dims the content behind it, making the rest of the page inaccessible.
-
它位于视口的中心,不锚定到任何特定的参考元素。
¥It is centered in the viewport, not anchored to any particular reference element.
基础
¥Essentials
可访问的对话框组件具有以下品质:
¥An accessible dialog component has the following qualities:
-
退出:当用户在打开的对话框外按
esc
键或时,它将关闭。¥Dismissal: When the user presses the
esc
key or outside the dialog while it is open, it closes. -
角色:这些元素被赋予了相关的角色和 ARIA 属性,以便屏幕阅读器可以访问。
¥Role: The elements are given relevant role and ARIA attributes to be accessible to screen readers.
-
焦点管理:焦点完全被困在对话框内,必须由用户关闭。
¥Focus management: Focus is fully trapped inside the dialog and must be dismissed by the user.
示例
¥Examples
下面有部分对这两个示例进行了深入解释。
¥Both of these examples have sections explaining them in-depth below.
基本对话框
¥Basic dialog
此示例演示如何创建在单个实例中使用的对话框以熟悉基础知识。
¥This example demonstrates how to create a dialog for use in a single instance to familiarize yourself with the fundamentals.
让我们看一下这个例子:
¥Let’s walk through the example:
打开状态
¥Open state
isOpen
确定对话框当前是否在屏幕上打开。它用于条件渲染。
¥isOpen
determines whether or not the dialog is
currently open on the screen. It is used for conditional
rendering.
useFloating 钩子
¥useFloating Hook
useFloating()
Hook 为我们的对话框提供了上下文。我们需要向它传递一些信息:
¥The useFloating()
Hook provides context for our dialog. We
need to pass it some information:
-
open
:上面useState()
Hook 的打开状态。¥
open
: The open state from ouruseState()
Hook above. -
onOpenChange
:打开或关闭对话框时将调用的回调函数。我们将使用它来更新我们的isOpen
状态。¥
onOpenChange
: A callback function that will be called when the dialog is opened or closed. We’ll use this to update ourisOpen
state.
与钩子交互
¥Interaction Hooks
交互钩子返回包含属性键的对象,这些属性使对话框能够打开、关闭或可供屏幕阅读器访问。
¥Interaction Hooks return objects containing keys of props that enable the dialog to be opened, closed, or accessible to screen readers.
使用从 Hook 返回的 context
,调用交互 Hooks:
¥Using the context
that was returned from the Hook,
call the interaction Hooks:
-
useClick()
添加了单击参考元素时打开或关闭对话框的功能。不过,对话框可能不会附加到参考元素,因此这是可选的。¥
useClick()
adds the ability to toggle the dialog open or closed when the reference element is clicked. A dialog may not be attached to a reference element though, so this is optional. -
useDismiss()
添加了当用户按esc
键或按对话框外部时关闭对话框的功能。outsidePressEvent
选项设置为'mousedown'
,以便触摸事件变得惰性并且不会穿过背景,因为默认行为是预先的。¥
useDismiss()
adds the ability to dismiss the dialog when the user presses theesc
key or presses outside of the dialog. TheoutsidePressEvent
option is set to'mousedown'
so that touch events become lazy and do not fall through the backdrop, as the default behavior is eager. -
useRole()
将dialog
的正确 ARIA 属性添加到对话框和参考元素中。¥
useRole()
adds the correct ARIA attributes for adialog
to the dialog and reference elements.
最后,useInteractions()
将他们所有的 props 合并为可用于渲染的 prop getter。
¥Finally, useInteractions()
merges all of their props into
prop getters which can be used for rendering.
在这之后:
¥After this:
-
useId()
为对话框的标题和描述元素生成唯一的 id,以便屏幕阅读器以广泛的兼容性宣布对话框的内容。¥
useId()
generates a unique id for the heading and description elements of the dialog, so that the content of the dialog is announced by screen readers with wide compatibility.
渲染
¥Rendering
现在我们已经设置了所有变量和 Hooks,我们可以渲染我们的元素。
¥Now we have all the variables and Hooks set up, we can render out our elements.
-
{...getReferenceProps()}
/{...getFloatingProps()}
将交互 Hook 中的 props 传播到相关元素上。它们包含onClick
、aria-expanded
等属性。¥
{...getReferenceProps()}
/{...getFloatingProps()}
spreads the props from the interaction Hooks onto the relevant elements. They contain props likeonClick
,aria-expanded
, etc. -
<FloatingOverlay />
是一个在浮动元素后面渲染背景覆盖元素的组件,具有锁定正文滚动的能力。FloatingOverlay
文档。¥
<FloatingOverlay />
is a component that renders a backdrop overlay element behind the floating element, with the ability to lock the body scroll.FloatingOverlay
docs. -
<FloatingFocusManager />
是一个管理模式行为对话框焦点的组件,将焦点捕获在内部。它应该直接封装浮动元素,并且仅在渲染对话框时才渲染。FloatingFocusManager
文档。¥
<FloatingFocusManager />
is a component that manages focus of the dialog for modal behavior, trapping focus inside. It should directly wrap the floating element and only be rendered when the dialog is also rendered.FloatingFocusManager
docs.
可重用的对话框组件
¥Reusable dialog component
最好创建一个可重用的组件 API,可以更轻松地在各种不同的场景中使用。我们可以将所有 Hook 放入单个自定义 Hook 中,以获得更好的可重用性,然后由封装状态的控制器组件使用。
¥It is better to create a reusable component API that can be used in a variety of different scenarios more easily. We can place all of our Hooks into a single custom Hook for better reusability, which is then used by a controller component which encapsulates the state.
可重复使用的组件可以:
¥The reusable component can:
-
不受控制或受控制
¥Be uncontrolled or controlled
-
接受任何元素作为
<DialogTrigger />
¥Accept any element as the
<DialogTrigger />
-
读取打开状态改变样式
¥Read the open state to change styles
控制器组件
¥Controller component
<Dialog />
这是管理对话框状态并向其余组件提供 API 的控制器组件。
¥This is the controller component that manages the dialog’s state and provides the API to the rest of the components.
渲染组件
¥Render components
这些组件读取根对话框组件提供的上下文并渲染适当的元素。
¥These components read the context provided by the root Dialog component and render the appropriate elements.
组件必须封装在 forwardRef()
中以允许引用,并且应该合并引用以确保所有引用都被保留并转发到元素。属性也被合并以防止覆盖。
¥The components must be wrapped in forwardRef()
to allow
refs, and should merge the refs to ensure all refs are preserved
and forwarded to the element. Props are also merged to prevent
overwriting.
-
<DialogTrigger />
是对话框所附加的触发按钮。如果你想将asChild
属性附加到自定义元素,则它接受asChild
属性。它还具有基于打开/关闭状态附加到样式的data-state
。¥
<DialogTrigger />
is the trigger button the dialog is attached to. This accepts anasChild
prop if you want to attach it to a custom element. It also has adata-state
attached to style based on the open/closed state. -
<DialogContent />
是对话框元素,它可以包含任何子元素(React 节点)。¥
<DialogContent />
is the dialog element, which can contain any children (React nodes). -
<DialogHeading />
是对话框的标题元素。¥
<DialogHeading />
is the heading element for the dialog. -
<DialogDescription />
是对话框的描述元素。¥
<DialogDescription />
is the description element for the dialog. -
<DialogClose />
是对话框的关闭按钮。¥
<DialogClose />
is the close button for the dialog.