Modal
基础对话框基于 React Portal 的模态框组件,支持尺寸、全屏、垂直居中、滚动布局与多种弹出位置,内置焦点管理、背景滚动锁定与自定义过渡动画,可通过页眉、正文、页脚等子组件自由组合内容
Component Demo
Basic usage and examples of the Modal component
基础用法
标题与描述
可选尺寸
垂直居中
滚动长内容
全屏模态框
入场方向
弹出位置
自定义尺寸
遮罩与键盘
自定义结构
确认对话框
API Documentation
Complete API reference for the Modal component
Props
| 属性名 | 类型 | 默认值 | 描述 |
|---|---|---|---|
isOpen | boolean | false | 受控的打开状态,为 `true` 时模态框打开 |
onOpenChange | (isOpen: boolean) => void | - | 打开状态变化回调,模态框通过它请求关闭(如 Esc 键、遮罩点击、`ModalClose`),由使用者更新 `isOpen` |
backdrop | ModalBackdrop | true | 背景遮罩行为,为 `false` 时不渲染遮罩且内容区自动添加 `shadow-lg` 阴影(点击内容以外区域仍可关闭),为 `"static"` 时点击遮罩不会关闭 |
keyboard | boolean | true | 是否允许通过 Esc 键关闭模态框 |
placement | ModalPlacement | - | 弹出位置,指定后使用弹出式布局(居中、顶部、底部、左侧、右侧),不指定时使用标准 Bootstrap 布局,`size`、`fullscreen`、`centered`、`scrollable` 等布局属性仅在标准布局下生效 |
direction | ModalDirection | - | 入场动画方向,指定后内容始终在视口中部展示,`left`/`right`/`top`/`bottom` 分别从对应方向滑入一段距离,`center` 为居中缩放动画;未指定时使用默认入场动画与默认布局(是否垂直居中由 `centered` 控制);指定 `placement` 时由 `placement` 控制布局与动画 |
width | number | string | - | 内容区宽度,数字按像素处理 |
height | number | string | - | 内容区高度,数字按像素处理,内容超出高度时正文区域出现滚动条 |
maxWidth | number | string | - | 内容区最大宽度,数字按像素处理 |
size | ModalSize | - | 模态框尺寸,`sm`、`lg`、`xl` 对应 300px、800px 与 1140px |
fullscreen | ModalFullscreen | false | 是否全屏显示,支持断点后缀(如 `"sm-down"`)在指定断点以下全屏 |
centered | boolean | false | 是否在视口中垂直居中显示模态框 |
scrollable | boolean | false | 是否让正文区域可滚动,页眉与页脚保持固定 |
duration | number | 300 | 打开与关闭动画时长(毫秒),系统开启减少动态效果时自动为 0 |
ariaLabel | string | - | 无障碍标签,不提供时通过 `ModalTitle` 生成的 id 关联标题 |
className | string | - | 模态框根元素自定义类名 |
backdropClassName | string | - | 遮罩层自定义类名 |
dialogClassName | string | - | 对话框容器(modal-dialog)自定义类名,仅标准布局下生效 |
contentClassName | string | - | 内容区(modal-content)自定义类名 |
backdropStyle | CSSProperties | - | 遮罩层自定义内联样式 |
dialogStyle | CSSProperties | - | 对话框容器自定义内联样式,仅标准布局下生效 |
contentStyle | CSSProperties | - | 内容区自定义内联样式 |
children | ReactNode | - | 模态框内容,支持任意 React 节点,也支持直接传入 `ModalDialog` 与 `ModalContent` 自定义结构 |
...rest | DialogHTMLAttributes | - | 透传原生 dialog 元素的所有属性(如 `onClick`、`onKeyDown` 等) |
Type Definitions
ModalSize
模态框尺寸类型
export type ModalSize = 'lg' | 'sm' | 'xl';ModalFullscreen
模态框全屏类型
export type ModalFullscreen = 'lg-down' | 'md-down' | 'sm-down' | 'xl-down' | 'xxl-down' | boolean;ModalBackdrop
模态框遮罩行为类型
export type ModalBackdrop = 'static' | boolean;ModalPlacement
模态框弹出位置类型
export type ModalPlacement = 'bottom' | 'center' | 'left' | 'right' | 'top';ModalDirection
模态框入场动画方向类型
export type ModalDirection = 'bottom' | 'center' | 'left' | 'right' | 'top';ModalAnimationStatus
模态框动画状态类型
export type ModalAnimationStatus = 'closed' | 'closing' | 'opened' | 'opening';ModalProps
模态框组件属性接口
export interface ModalProps extends Omit<DialogHTMLAttributes<HTMLDialogElement>, 'children'> {
ariaLabel?: string;
backdrop?: ModalBackdrop;
backdropClassName?: string;
backdropStyle?: CSSProperties;
centered?: boolean;
children: ReactNode;
className?: string;
contentClassName?: string;
contentStyle?: CSSProperties;
dialogClassName?: string;
dialogStyle?: CSSProperties;
direction?: ModalDirection;
duration?: number;
fullscreen?: ModalFullscreen;
height?: number | string;
isOpen?: boolean;
keyboard?: boolean;
maxWidth?: number | string;
onOpenChange?: (isOpen: boolean) => void;
placement?: ModalPlacement;
scrollable?: boolean;
size?: ModalSize;
style?: CSSProperties;
width?: number | string;
}ModalContextValue
模态框上下文,供 ModalContent、ModalTitle、ModalDescription、ModalClose 等子组件消费
export interface ModalContextValue {
backdrop: ModalBackdrop;
close: () => void;
contentRef: RefObject<HTMLDivElement | null>;
descriptionId: string;
direction?: ModalDirection;
handleContentTransitionEnd: (event: TransitionEvent<HTMLDivElement>) => void;
placement?: ModalPlacement;
sizingStyle: CSSProperties;
status: ModalAnimationStatus;
titleId: string;
}ModalPartProps
模态框子组件属性接口(ModalDialog、ModalContent、ModalHeader、ModalTitle、ModalDescription、ModalBody、ModalFooter、ModalClose)
export interface ModalDialogProps extends HTMLAttributes<HTMLDivElement> {
centered?: boolean;
children?: ReactNode;
className?: string;
fullscreen?: ModalFullscreen;
scrollable?: boolean;
size?: ModalSize;
}
export interface ModalContentProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
className?: string;
}
export interface ModalHeaderProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
className?: string;
closeButton?: boolean;
closeLabel?: string;
}
export interface ModalTitleProps extends HTMLAttributes<HTMLElement> {
as?: ElementType;
children?: ReactNode;
className?: string;
}
export interface ModalDescriptionProps extends HTMLAttributes<HTMLElement> {
as?: ElementType;
children?: ReactNode;
className?: string;
}
export interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
className?: string;
}
export interface ModalFooterProps extends HTMLAttributes<HTMLDivElement> {
children?: ReactNode;
className?: string;
}
export interface ModalCloseProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children?: ReactNode;
className?: string;
}