对话框 · Dialog
展示模态内容,并在打开和关闭时管理焦点。
安装与前置条件
npm install @astryxdesign/core@0.7.1 @astryxdesign/theme-neutral@0.7.1 @stylexjs/stylex@0.19.0
需要 React 19+,按顺序导入基础 CSS 和主题,并设置 Theme Provider。参见开始使用。
示例与使用方式
- 对话框 · 综合展示 1:首先体验这个示例,再查看代码理解组件的组合方式。
- 对话框 · 综合展示 2:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 3:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 4:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 5:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 6:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 基础用法 7:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 8:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
- 对话框 · 交互示例 9:可交互查看这一用法的行为,复制代码时保留它实际使用的属性与导入。
API 与上游详细参考
优先使用 0.7.1 官方中文说明;上游尚未提供中文的条目保留英文。属性名、类型及默认值保持原生 API,不把示例状态名称当成组件属性。
Dialog
Dialog displays a modal overlay that blocks interaction with the page until the user responds. Use it for delete confirmations, edit forms, terms acceptance, or any decision that should not be skipped.
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| isOpen * | boolean | Whether the dialog is open. | |
| onOpenChange * | (isOpen: boolean) => unknown | Callback when dialog visibility changes. | |
| children * | ReactNode | Dialog content. | |
| width | number | string | 400 | Preferred width of the dialog in pixels or any CSS value. Standard dialogs clamp to their container and the dynamic viewport with spacing-token gutters so narrow viewports keep content on screen. |
| maxHeight | number | string | '75dvh' | Maximum height of the dialog. Defaults to a dynamic viewport value so browser UI changes are reflected where supported. |
| position | DialogPosition | Static position for the dialog; centered by default when omitted. Use logical start/end for inline offsets so positioned dialogs mirror correctly under RTL. | |
| variant | 'standard' | 'fullscreen' | 'standard' | Dialog variant: fullscreen expands to fill the entire viewport. |
| purpose | 'required' | 'form' | 'info' | 'info' | Controls dismissal behavior: required disables Escape and backdrop click; form disables backdrop click after interaction; info allows both. |
| padding | 0 | 0.5 | 1 | 1.5 | 2 | 3 | 4 | 5 | 6 | 8 | 10 | Internal padding of the dialog using the spacing scale step. | |
| isInline | boolean | false | Renders dialog content inline without the <dialog> element, backdrop, or modal behavior. For documentation previews and showcases only. |
使用建议
- Choose the right purpose: info for dismissable content, form to prevent accidental backdrop dismissal, required when the user must respond.
- Include a clear title in the header so users immediately understand what the dialog is asking.
- Use purpose="form" for dialogs with inputs so the user can't accidentally lose data by clicking the backdrop.
- Keep dialogs focused on a single task; if the content grows beyond what fits, consider a full page instead.
- 避免:Use a dialog for simple messages that could be shown inline or as a toast notification.
- 避免:Nest dialogs inside other dialogs; restructure the flow into steps within a single dialog instead.
- 避免:Use the fullscreen variant for simple confirmations; it is meant for complex content like editors or long forms.
主题 API
{
"container": true,
"targets": [
{
"className": "astryx-dialog",
"visualProps": [
"variant"
]
},
{
"className": "astryx-dialog-header"
},
{
"className": "astryx-dialog-header-start-content"
},
{
"className": "astryx-dialog-header-title-block"
},
{
"className": "astryx-dialog-header-end-content"
},
{
"className": "astryx-dialog-header-close-icon"
}
],
"vars": [
{
"name": "--_dialog-radius",
"description": "Border radius of the dialog",
"default": "var(--radius-container)",
"private": true
}
],
"derived": [
{
"property": "borderRadius",
"vars": [
"--_dialog-radius"
]
},
{
"property": "padding",
"expand": "container"
}
]
}
DialogHeader
useImperativeDialog
组件结构
- Header: Title, optional subtitle, and close button. The title receives focus on open and labels the dialog via aria-labelledby.
- Body: The main content area: text, forms, lists, or any layout.
- Footer: Action buttons like Save/Cancel or Accept/Decline, aligned to the end.
- Backdrop: Semi-transparent overlay behind the dialog that blocks page interaction.
Dialog Header
使用 DialogHeader 为对话框提供带标签的标题区和可选的关闭控件。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| title | ReactNode | 对话框标题,渲染在可聚焦的 h2 中(打开时获得焦点,其文本内容通过 aria-labelledby 为对话框命名)。请使用非空、非交互的行内内容。 | |
| subtitle | ReactNode | 标题下方的副标题,可包含链接等行内内容;避免使用块级元素。 | |
| onOpenChange | (isOpen: boolean) => unknown | 关闭按钮的回调(省略时不显示按钮)。 | |
| startContent | ReactNode | 标题之前的内容(例如返回按钮)。 | |
| endContent | ReactNode | 标题之后、关闭按钮之前的内容。 | |
| endContentEdgeCompensation | 'inline' | 'block' | 'all' | 选择尾部内容插槽的补偿轴;省略时保留关闭操作的自动补偿。 | |
| hasDivider | boolean | true | 在底部边缘添加分隔线。 |
Basic
import {DialogHeader} from '@astryxdesign/core/Dialog';
<DialogHeader title="Delete file?" subtitle="This action cannot be undone." />;
With close button
import {useState} from 'react';
import {DialogHeader} from '@astryxdesign/core/Dialog';
function Header() {
const [, setIsOpen] = useState(true);
// Passing onOpenChange renders a close button that calls it with false.
return <DialogHeader title="Settings" onOpenChange={setIsOpen} />;
}
With a link in the subtitle
import {DialogHeader} from '@astryxdesign/core/Dialog';
import {Link} from '@astryxdesign/core/Link';
<DialogHeader
title="Share conversation"
subtitle={
<>
Anyone with the link can view it. Review the{' '}
<Link href="#sharing-policy">sharing policy</Link> first.
</>
}
/>;
With start and end content
import {DialogHeader} from '@astryxdesign/core/Dialog';
import {Icon} from '@astryxdesign/core/Icon';
import {Badge} from '@astryxdesign/core/Badge';
<DialogHeader
title="Notifications"
startContent={<Icon icon="chevronLeft" size="sm" />}
endContent={<Badge label="3" />}
/>;
主题 API
{
"targets": [
{
"className": "astryx-dialog-header"
},
{
"className": "astryx-dialog-header-start-content"
},
{
"className": "astryx-dialog-header-title-block"
},
{
"className": "astryx-dialog-header-end-content"
},
{
"className": "astryx-dialog-header-close-icon"
}
]
}
组件结构
- Header row: 排列标题区、可选的首尾内容和关闭控件。
- Start content: 包装可选的首部内容。
- Title block: 组合标题和可选副标题。
- End content: 组合可选尾部内容和可选关闭控件。
- Close icon: 关闭按钮内的关闭图标。
useImperativeDialog
Hook for showing a dialog without managing open state. Call dialog.show(content, options) to open and dialog.hide() to close. Render dialog.element in your JSX tree.
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
| show | (content: ReactNode, options?: DialogOptions) => void | Show the dialog with the given content. Options are the same as Dialog props minus isOpen/onOpenChange/children. | |
| hide | () => void | Hide the dialog. | |
| isOpen | boolean | Whether the dialog is currently open. | |
| element | ReactNode | The dialog element: render this in your JSX tree. |