对话框
在模态界面中进行确认、账户选择或表单输入。
本指南覆盖默认 Emotion 环境的 Material UI Core;扩展包与额外示例按清单单独标注。
使用场景与业务边界
关闭弹框不代表提交成功;保留焦点返回、可访问标题和取消路径。
原生组成与范围
Dialog, DialogTitle, DialogContent, DialogContentText, DialogActions, Slide
保持 Material UI 原生组合与类型,不替换为 JGuang/Base UI/Radix 同名 API。示例条目不是额外组件。
原生安装与初始化
npm install @mui/material@9.4.0 @emotion/react@11.14.0 @emotion/styled@11.14.1
采用原生 npm 包与 Emotion,不提供虚构的 JGuang UI Registry 地址。将示例放在原生 ThemeProvider 内,按项目选择 CssBaseline 或 ScopedCssBaseline。先检查 React、现有 Provider、锁文件与 SSR 配置;不要覆盖用户文件或忽略 peer 冲突。本批实际验收 React 19.2.8;React 18 及以下须匹配 react-is。完整初始化规则见随附的双语 setup 文档。
关键原生参数
仅解释本指南选出的关键参数,不是平铺的通用 API。原生继承来源、slot 结构、可空值与泛型仍按固定源码保留。
| 所属组件.属性 | 用途说明 | 声明来源 |
|---|---|---|
Dialog.open | 受控原生可见性,不获取数据或执行操作。 | Dialog |
Dialog.onClose | 原生关闭请求,reason/event 签名因组件不同,宿主须更新 open。 | Dialog |
Dialog.fullScreen | 使用全屏 Dialog,响应式判断由宿主负责。 | Dialog |
Dialog.maxWidth | 原生 Container/Dialog 断点宽度,false 去除原生限制。 | Dialog |
可运行原生示例
下列机器键只选择示例入口,不会作为通用 variant 属性传入每个组件。原生示例 JSX 与数据保持上游原文;JGuang 编写的验收示例明确标注。
- 基础介绍 ·
SimpleDialogDemo· 上游原生示例 - 警告提示 ·
AlertDialog· 上游原生示例 - 多种过渡动画 ·
AlertDialogSlide· 上游原生示例 - 表单对话框 ·
FormDialog· 上游原生示例 - 定制样式 ·
CustomizedDialogs· 上游原生示例 - 全屏对话框 ·
FullScreenDialog· 上游原生示例 - 可选尺寸 ·
MaxWidthDialog· 上游原生示例 - 响应式全屏 ·
ResponsiveDialog· 上游原生示例 - 确认对话框 ·
ConfirmationDialog· 上游原生示例 - 非模态对话框 ·
CookiesBanner· 上游原生示例 - 长内容滚动 ·
ScrollDialog· 上游原生示例
尚未支持的额外示例
这些条目仍保留在上游清单中,不静默跳过,也不展示为已完成预览。需要补充依赖/框架验收后再纳入可运行列表。
- 可拖动对话框扩展 ·
DraggableDialog:react-draggable
真实使用示例
固定版本的未修改原生示例;复制时同时保留所需的局部辅助文件。
import * as React from 'react';
import Button from '@mui/material/Button';
import Avatar from '@mui/material/Avatar';
import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem';
import ListItemAvatar from '@mui/material/ListItemAvatar';
import ListItemButton from '@mui/material/ListItemButton';
import ListItemText from '@mui/material/ListItemText';
import DialogTitle from '@mui/material/DialogTitle';
import Dialog from '@mui/material/Dialog';
import PersonIcon from '@mui/icons-material/Person';
import AddIcon from '@mui/icons-material/Add';
import Typography from '@mui/material/Typography';
import { blue } from '@mui/material/colors';
const emails = ['username@gmail.com', 'user02@gmail.com'];
export interface SimpleDialogProps {
open: boolean;
selectedValue: string;
onClose: (value: string) => void;
}
function SimpleDialog(props: SimpleDialogProps) {
const { onClose, selectedValue, open } = props;
const handleClose = () => {
onClose(selectedValue);
};
const handleListItemClick = (value: string) => {
onClose(value);
};
return (
<Dialog onClose={handleClose} open={open}>
<DialogTitle>Set backup account</DialogTitle>
<List sx={{ pt: 0 }}>
{emails.map((email) => (
<ListItem disablePadding key={email}>
<ListItemButton onClick={() => handleListItemClick(email)}>
<ListItemAvatar>
<Avatar sx={{ bgcolor: blue[100], color: blue[600] }}>
<PersonIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary={email} />
</ListItemButton>
</ListItem>
))}
<ListItem disablePadding>
<ListItemButton
autoFocus
onClick={() => handleListItemClick('addAccount')}
>
<ListItemAvatar>
<Avatar>
<AddIcon />
</Avatar>
</ListItemAvatar>
<ListItemText primary="Add account" />
</ListItemButton>
</ListItem>
</List>
</Dialog>
);
}
export default function SimpleDialogDemo() {
const [open, setOpen] = React.useState(false);
const [selectedValue, setSelectedValue] = React.useState(emails[1]);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = (value: string) => {
setOpen(false);
setSelectedValue(value);
};
return (
<div>
<Typography variant="subtitle1" component="div">
Selected: {selectedValue}
</Typography>
<br />
<Button variant="outlined" onClick={handleClickOpen}>
Open simple dialog
</Button>
<SimpleDialog
selectedValue={selectedValue}
open={open}
onClose={handleClose}
/>
</div>
);
}
示例依赖边界
react, @mui/material/Button, @mui/material/Avatar, @mui/material/List, @mui/material/ListItem, @mui/material/ListItemAvatar, @mui/material/ListItemButton, @mui/material/ListItemText, @mui/material/DialogTitle, @mui/material/Dialog, @mui/icons-material/Person, @mui/icons-material/Add, @mui/material/Typography, @mui/material/colors, @mui/material/DialogActions, @mui/material/DialogContent, @mui/material/DialogContentText, @mui/material/Slide, @mui/material/transitions, @mui/material/TextField, @mui/material/styles, @mui/material/IconButton, @mui/icons-material/Close, @mui/material/Divider, @mui/material/AppBar, @mui/material/Toolbar, @mui/material/Box, @mui/material/FormControl, @mui/material/FormControlLabel, @mui/material/InputLabel, @mui/material/MenuItem, @mui/material/Select, @mui/material/Switch, @mui/material/useMediaQuery, @mui/material/RadioGroup, @mui/material/Radio, @mui/material/Stack, @mui/material/Unstable_TrapFocus, @mui/material/CssBaseline, @mui/material/Container, @mui/icons-material/Menu, @mui/material/Paper, @mui/material/Fade
直接导入 Icons/System/Utils 的示例需要匹配 9.4.0 包。局部数据与辅助文件属于示例闭包,不是额外组件。远程图片和模拟操作不提供后端。
固定上游 API 元数据参考
以下表格保留上游元数据,不是重新推断的通用类型体系。条件泛型、继承属性与回调细节以以下源码声明为准。主题默认配置可能覆盖元数据默认值。
Dialog
import Dialog from '@mui/material/Dialog';
import { Dialog } from '@mui/material';
原生继承: Modal. 父级与 DOM 属性未被伪造为本组件新属性。
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
open | 是 | bool | — |
aria-describedby | 否 | string | — |
aria-labelledby | 否 | string | — |
aria-modal | 否 | 'false' | 'true' | bool | true |
children | 否 | node | — |
classes | 否 | object | — |
fullScreen | 否 | bool | false |
fullWidth | 否 | bool | false |
maxWidth | 否 | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | false | string | 'sm' |
onClose | 否 | func | — |
PaperComponent | 否 | elementType | Paper |
role | 否 | 'alertdialog' | 'dialog' | 'dialog' |
scroll | 否 | 'body' | 'paper' | 'paper' |
slotProps | 否 | { backdrop?: func | object, container?: func | object, paper?: func | object, root?: func | object, transition?: func | object } | {} |
slots | 否 | { backdrop?: elementType, container?: elementType, paper?: elementType, root?: elementType, transition?: elementType } | {} |
sx | 否 | Array<func | object | bool> | func | object | — |
transitionDuration | 否 | number | { appear?: number, enter?: number, exit?: number } | { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen, } |
DialogTitle
import DialogTitle from '@mui/material/DialogTitle';
import { DialogTitle } from '@mui/material';
原生继承: Typography. 父级与 DOM 属性未被伪造为本组件新属性。
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
children | 否 | node | — |
classes | 否 | object | — |
sx | 否 | Array<func | object | bool> | func | object | — |
DialogContent
import DialogContent from '@mui/material/DialogContent';
import { DialogContent } from '@mui/material';
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
children | 否 | node | — |
classes | 否 | object | — |
dividers | 否 | bool | false |
sx | 否 | Array<func | object | bool> | func | object | — |
DialogContentText
import DialogContentText from '@mui/material/DialogContentText';
import { DialogContentText } from '@mui/material';
原生继承: Typography. 父级与 DOM 属性未被伪造为本组件新属性。
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
children | 否 | node | — |
classes | 否 | object | — |
sx | 否 | Array<func | object | bool> | func | object | — |
DialogActions
import DialogActions from '@mui/material/DialogActions';
import { DialogActions } from '@mui/material';
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
children | 否 | node | — |
classes | 否 | object | — |
disableSpacing | 否 | bool | false |
sx | 否 | Array<func | object | bool> | func | object | — |
Slide
import Slide from '@mui/material/Slide';
import { Slide } from '@mui/material';
原生继承: Transition. 父级与 DOM 属性未被伪造为本组件新属性。
| 属性 | 必需 | 上游元数据类型/约束 | 元数据默认值 |
|---|---|---|---|
children | 是 | element | — |
addEndListener | 否 | func | — |
appear | 否 | bool | true |
container | 否 | HTML element | func | — |
direction | 否 | 'down' | 'left' | 'right' | 'up' | 'down' |
disablePrefersReducedMotion | 否 | bool | false |
easing | 否 | { enter?: string, exit?: string } | string | { enter: theme.transitions.easing.easeOut, exit: theme.transitions.easing.sharp, } |
in | 否 | bool | — |
timeout | 否 | number | { appear?: number, enter?: number, exit?: number } | { enter: theme.transitions.duration.enteringScreen, exit: theme.transitions.duration.leavingScreen, } |
原生源码声明
声明与 import 从固定源码提取,不平铺联合类型或外部继承。英文注释/类型属于原始源码参考,不代表上游正文已全文翻译。共享类型仍位于原生包中。
vendor/src/Dialog/Dialog.d.ts
import * as React from 'react';
import { SxProps, Breakpoint } from '@mui/system';
import { Theme } from '../styles';
import { InternalStandardProps as StandardProps } from '../internal';
import { BackdropProps } from '../Backdrop';
import { PaperProps } from '../Paper';
import { ModalProps } from '../Modal';
import { TransitionProps } from '../transitions/types';
import { DialogClasses } from './dialogClasses';
import { CreateSlotsAndSlotProps, SlotComponentProps, SlotProps } from '../utils/types';
export interface DialogSlots {
/**
* The component that renders the transition.
* [Follow this guide](/material-ui/transitions/#transition-slots) to learn more about the requirements for this component.
* @default Collapse
*/
transition?: React.ElementType | undefined;
/**
* The component that renders the paper.
* @default Paper
*/
paper?: React.ElementType | undefined;
/**
* The component that renders the container.
*/
container?: React.ElementType | undefined;
/**
* The component that renders the backdrop.
*/
backdrop?: React.ElementType | undefined;
/**
* The component that renders the root.
*/
root?: React.ElementType | undefined;
}
export interface DialogTransitionSlotPropsOverrides {}
export interface DialogPaperSlotPropsOverrides {}
export interface DialogContainerSlotPropsOverrides {}
export interface DialogBackdropSlotPropsOverrides {}
export interface DialogRootSlotPropsOverrides {}
export type DialogSlotsAndSlotProps = CreateSlotsAndSlotProps<
DialogSlots,
{
/**
* Props forwarded to the root slot.
* By default, the available props are based on the [Modal](https://mui.com/material-ui/api/modal/#props) component.
*/
root: SlotProps<React.ElementType<ModalProps>, DialogRootSlotPropsOverrides, DialogOwnerState>;
/**
* Props forwarded to the backdrop slot.
* By default, the available props are based on the [Backdrop](https://mui.com/material-ui/api/backdrop/#props) component.
*/
backdrop: SlotProps<
React.ElementType<BackdropProps>,
DialogBackdropSlotPropsOverrides,
DialogOwnerState
>;
/**
* Props forwarded to the container slot.
* By default, the available props are based on a div element.
*/
container: SlotProps<'div', DialogContainerSlotPropsOverrides, DialogOwnerState>;
/**
* Props forwarded to the transition slot.
* By default, the available props are based on the [Fade](https://mui.com/material-ui/api/fade/#props) component.
*/
transition: SlotComponentProps<
React.ElementType<TransitionProps>,
TransitionProps & DialogTransitionSlotPropsOverrides,
DialogOwnerState
>;
/**
* Props forwarded to the paper slot.
* By default, the available props are based on the [Paper](https://mui.com/material-ui/api/paper/#props) component.
*/
paper: SlotProps<
React.ElementType<PaperProps>,
DialogPaperSlotPropsOverrides,
DialogOwnerState
>;
}
>;
export interface DialogProps
extends
Omit<StandardProps<ModalProps, 'children'>, 'slots' | 'slotProps'>,
DialogSlotsAndSlotProps {
/**
* The id(s) of the element(s) that describe the dialog.
*/
'aria-describedby'?: string | undefined;
/**
* The id(s) of the element(s) that label the dialog.
*/
'aria-labelledby'?: string | undefined;
/**
* Informs assistive technologies that the element is modal.
* It's added on the element with role="dialog".
* @default true
*/
'aria-modal'?: boolean | 'true' | 'false' | undefined;
/**
* Dialog children, usually the included sub-components.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<DialogClasses> | undefined;
/**
* If `true`, the dialog is full-screen.
* @default false
*/
fullScreen?: boolean | undefined;
/**
* If `true`, the dialog stretches to `maxWidth`.
*
* Notice that the dialog width grow is limited by the default margin.
* @default false
*/
fullWidth?: boolean | undefined;
/**
* Determine the max-width of the dialog.
* The dialog width grows with the size of the screen.
* Set to `false` to disable `maxWidth`.
* @default 'sm'
*/
maxWidth?: Breakpoint | false | undefined;
/**
* Callback fired when the component requests to be closed.
*
* @param {object} event The event source of the callback.
* @param {string} reason Can be: `"escapeKeyDown"`, `"backdropClick"`.
*/
onClose?: ModalProps['onClose'] | undefined;
/**
* If `true`, the component is shown.
*/
open: ModalProps['open'];
/**
* The ARIA role for the dialog element.
* The main dialog role is `dialog`, but `alertdialog` can be used if the content of the dialog requires immediate attention.
* See https://www.w3.org/TR/wai-aria-1.2/#dialog and https://www.w3.org/TR/wai-aria-1.2/#alertdialog for more details.
* @default 'dialog'
*/
role?: 'dialog' | 'alertdialog' | undefined;
/**
* The component used to render the body of the dialog.
* @default Paper
*/
PaperComponent?: React.JSXElementConstructor<PaperProps> | undefined;
/**
* Determine the container for scrolling the dialog.
* @default 'paper'
*/
scroll?: 'body' | 'paper' | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
* @default {
* enter: theme.transitions.duration.enteringScreen,
* exit: theme.transitions.duration.leavingScreen,
* }
*/
transitionDuration?: TransitionProps['timeout'] | undefined;
}
export default function Dialog(props: DialogProps): React.JSX.Element;
export interface DialogOwnerState extends Omit<DialogProps, 'slots' | 'slotProps'> {}
vendor/src/DialogTitle/DialogTitle.d.ts
import * as React from 'react';
import { SxProps } from '@mui/system';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';
import { Theme } from '../styles';
import { TypographyTypeMap } from '../Typography';
import { DialogTitleClasses } from './dialogTitleClasses';
export interface DialogTitleOwnProps extends Omit<TypographyTypeMap['props'], 'classes'> {
/**
* The content of the component.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<DialogTitleClasses> | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
}
export interface DialogTitleTypeMap<
AdditionalProps = {},
RootComponent extends React.ElementType = TypographyTypeMap['defaultComponent'],
> {
props: AdditionalProps & DialogTitleOwnProps;
defaultComponent: RootComponent;
}
declare const DialogTitle: OverridableComponent<DialogTitleTypeMap>;
export type DialogTitleProps<
RootComponent extends React.ElementType = DialogTitleTypeMap['defaultComponent'],
AdditionalProps = { component?: React.ElementType | undefined },
> = OverrideProps<DialogTitleTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType | undefined;
};
vendor/src/DialogContent/DialogContent.d.ts
import * as React from 'react';
import { SxProps } from '@mui/system';
import { Theme } from '../styles';
import { InternalStandardProps as StandardProps } from '../internal';
import { DialogContentClasses } from './dialogContentClasses';
export interface DialogContentProps extends StandardProps<React.HTMLAttributes<HTMLDivElement>> {
/**
* The content of the component.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<DialogContentClasses> | undefined;
/**
* Display the top and bottom dividers.
* @default false
*/
dividers?: boolean | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
}
export default function DialogContent(props: DialogContentProps): React.JSX.Element;
vendor/src/DialogContentText/DialogContentText.d.ts
import * as React from 'react';
import { SxProps } from '@mui/system';
import { TypographyTypeMap } from '../Typography';
import { OverrideProps, OverridableComponent } from '../OverridableComponent';
import { Theme } from '../styles';
import { DialogContentTextClasses } from './dialogContentTextClasses';
export interface DialogContentTextOwnProps extends Omit<TypographyTypeMap['props'], 'classes'> {
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<DialogContentTextClasses> | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
}
export interface DialogContentTextTypeMap<
AdditionalProps = {},
RootComponent extends React.ElementType = TypographyTypeMap['defaultComponent'],
> {
props: AdditionalProps & DialogContentTextOwnProps;
defaultComponent: RootComponent;
}
declare const DialogContentText: OverridableComponent<DialogContentTextTypeMap>;
export type DialogContentTextProps<
RootComponent extends React.ElementType = DialogContentTextTypeMap['defaultComponent'],
AdditionalProps = {},
> = OverrideProps<DialogContentTextTypeMap<AdditionalProps, RootComponent>, RootComponent> & {
component?: React.ElementType | undefined;
};
vendor/src/DialogActions/DialogActions.d.ts
import * as React from 'react';
import { SxProps } from '@mui/system';
import { Theme } from '../styles';
import { InternalStandardProps as StandardProps } from '../internal';
import { DialogActionsClasses } from './dialogActionsClasses';
export interface DialogActionsProps extends StandardProps<React.HTMLAttributes<HTMLDivElement>> {
/**
* The content of the component.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<DialogActionsClasses> | undefined;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme> | undefined;
/**
* If `true`, the actions do not have additional margin.
* @default false
*/
disableSpacing?: boolean | undefined;
}
export default function DialogActions(props: DialogActionsProps): React.JSX.Element;
vendor/src/Slide/Slide.d.ts
import * as React from 'react';
import { TransitionProps } from '../transitions/types';
export interface SlideProps extends TransitionProps {
/**
* Add a custom transition end trigger.
* Use it when you need custom logic to decide when the transition has ended.
* Note: Timeouts are still used as a fallback if provided.
*
* @param {HTMLElement} node The transitioning DOM node.
* @param {Function} done Call this when the transition has finished.
*/
addEndListener?: TransitionProps['addEndListener'] | undefined;
/**
* Perform the enter transition when it first mounts if `in` is also `true`.
* Set this to `false` to disable this behavior.
* @default true
*/
appear?: boolean | undefined;
/**
* A single child content element.
*/
children: React.ReactElement<unknown, any>;
/**
* An HTML element, or a function that returns one.
* It's used to set the container the Slide is transitioning from.
*/
container?: null | Element | ((element: Element) => Element) | undefined;
/**
* If `true`, the transition ignores `theme.motion.reducedMotion` and keeps its normal timing.
* @default false
*/
disablePrefersReducedMotion?: boolean | undefined;
/**
* Direction the child node will enter from.
* @default 'down'
*/
direction?: 'left' | 'right' | 'up' | 'down' | undefined;
/**
* The transition timing function.
* You may specify a single easing or a object containing enter and exit values.
* @default {
* enter: theme.transitions.easing.easeOut,
* exit: theme.transitions.easing.sharp,
* }
*/
easing?: TransitionProps['easing'] | undefined;
/**
* If `true`, the component will transition in.
*/
in?: TransitionProps['in'] | undefined;
ref?: React.Ref<unknown> | undefined;
/**
* The duration for the transition, in milliseconds.
* You may specify a single timeout for all transitions, or individually with an object.
* @default {
* enter: theme.transitions.duration.enteringScreen,
* exit: theme.transitions.duration.leavingScreen,
* }
*/
timeout?: TransitionProps['timeout'] | undefined;
}
export default function Slide(props: SlideProps): React.JSX.Element;
安装后验收
执行严格类型检查、生产构建和实际交互。检查键盘标签/焦点、原生支持的禁用/错误/只读语义、深浅色、窄屏和减少动画。按真实宿主数据检查回调,不把复制提示词当作安装完成。初始化工具还需检查服务端 HTML 与无告警水合。
来源与许可
https://github.com/mui/material-ui/tree/809a7717b4c050ba3f69b75300689f07c050a16e
MIT · @mui/material@9.4.0. 保留上游原始内容与许可证。上游完整原文保留于 vendor/docs,不标为全文中文化。