展示类

模态对话框

模态对话框用于等待用户响应、告知用户重要信息或在不丢失上下文的情况下展示更多信息

代码演示

如何引入

import { Modal } from '@fibrous/semi-ui-react';

基本

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
        console.log('Ok button clicked');
    };
    const handleCancel = () => {
        setVisible(false);
        console.log('Cancel button clicked');
    };
    const handleAfterClose = () => {
        console.log('After Close callback executed');
    };

    return (
        <>
            <Button onClick={showDialog}>打开弹窗</Button>
            <Modal title="基本对话框" visible={visible} onOk={handleOk} afterClose={handleAfterClose} onCancel={handleCancel} closeOnEsc>
                This is the content of a basic modal.
                <br />
                More content...
            </Modal>
        </>
    );
}

底部撑满

设置 footerFill 为 true 可使 Modal footer 底部按钮撑满排列

点击遮罩层不可关闭

修改 maskClosable 为 false 则不可通过点击遮罩层来关闭对话框。

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
    };
    const handleCancel = () => {
        setVisible(false);
    };
    return (
        <>
            <Button onClick={showDialog}>点击遮罩层不可关闭</Button>
            <Modal title="对话框标题" visible={visible} onOk={handleOk} onCancel={handleCancel} maskClosable={false}>
                <p>This is a modal that cannot be closed by clicking on the mask.</p>
                <p>More content...</p>
            </Modal>
        </>
    );
}

自定义按钮文字

通过设置 okText 与 cancelText 属性可自定义按钮显示的文字。

注意:命令式调用的 Modal 需要通过这两个属性来设置 i18 的文本,因为我们无法修改 React 组件树,命令式调用插入的 Component 无法消费到 Locale 相关的 Context

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
    };
    const handleCancel = () => {
        setVisible(false);
    };
    return (
        <>
            <Button onClick={showDialog}>自定义按钮文字</Button>
            <Modal title="自定义按钮文字" visible={visible} onOk={handleOk} onCancel={handleCancel} okText="Sounds great!" cancelText="No, thanks.">
                <p>This is a modal with customized button texts.</p>
                <p>More content...</p>
            </Modal>
        </>
    );
}

自定义按钮属性

通过设置 okButtonProps 与 cancelButtonProps 属性可自定义按钮的属性。其中的 onClick 先于内置处理调用,不会替换内置处理。

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
    };
    const handleCancel = () => {
        setVisible(false);
    };
    return (
        <>
            <Button onClick={showDialog}>自定义按钮属性</Button>
            <Modal title="自定义按钮属性" visible={visible} onOk={handleOk} onCancel={handleCancel} okButtonProps={{ size: 'small', type: 'warning' }} cancelButtonProps={{ size: 'small', disabled: true }}>
                <p>This is a modal with customized button props.</p>
                <p>More content...</p>
            </Modal>
        </>
    );
}

自定义对话框头部和页脚

如果需要实现更丰富的个性化需求,可以通过 header 自定义头部,footer 自定义页脚的按钮。把 header 设为 null时则不展示头部区域;不需要显示任何按钮时,同样可以把 footer 设为 null。

自定义对话框的样式

通过设置 style 可以自定义样式及位置如 style.top,也可以通过 centered 使对话框居中显示。也可以通过设置 maskStyle 自定义遮罩样式,及 bodyStyle 自定义对话框内容样式。

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
    };
    const handleCancel = () => {
        setVisible(false);
    };
    return (
        <>
            <Button onClick={showDialog}>自定义对话框样式</Button>
            <Modal title="自定义样式" visible={visible} onOk={handleOk} onCancel={handleCancel} centered bodyStyle={{ overflow: 'auto', height: 200 }}>
                <p style={{ lineHeight: 1.8 }}>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。</p>
                <p style={{ lineHeight: 1.8 }}>区别于其他的设计系统而言,Semi Design 以用户中心、内容优先、设计人性化为设计理念,具有以下优势:</p>
                <ul>
                    <li>
                        <p>Semi Design 以内容优先进行设计。</p>
                    </li>
                    <li>
                        <p>更容易地自定义主题。</p>
                    </li>
                    <li>
                        <p>适用国际化场景。</p>
                    </li>
                    <li>
                        <p>效率场景加入人性化关怀</p>
                    </li>
                </ul>
            </Modal>
        </>
    );
}

自定义的对话框

通过灵活使用使用 header,footer等属性可以实现一个完全自定义的对话框。

代码
import { useState } from 'react';
import { IconVigoLogo, IconSemiLogo } from '@fibrous/semi-icons-react';
import { Modal, Button, List } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const showDialog = () => {
        setVisible(true);
    };
    const handleOk = () => {
        setVisible(false);
    };
    const handleCancel = () => {
        setVisible(false);
    };
    const data = [
        {
            icon: <IconSemiLogo style={{ fontSize: 48 }} />,
            title: 'Boost new feature adoption with Integration',
            content: 'Sample data is prepared for you to demonstrate how Integration may be useful for your team',
        },
        {
            icon: <IconVigoLogo style={{ fontSize: 48 }} />,
            title: 'Introducing Dark Mode',
            content: 'Sample data is prepared for you to demonstrate how Integration may be useful for your team',
        },
        {
            icon: <IconSemiLogo style={{ fontSize: 48 }} />,
            title: 'New List Component',
            content: 'Sample data is prepared for you to demonstrate how Integration may be useful for your team',
        },
    ];
    const btnStyle = {
        width: 240,
        margin: '4px 50px',
    };
    const footer = (
        <div style={{ textAlign: 'center' }}>
            <Button type="primary" theme="solid" onClick={handleOk} style={btnStyle}>
                Continue
            </Button>
            <Button type="primary" theme="borderless" onClick={handleCancel} style={btnStyle}>
                Learn more features
            </Button>
        </div>
    );
    return (
        <>
            <Button onClick={showDialog}>自定义对话框</Button>
            <Modal header={null} visible={visible} onOk={handleOk} onCancel={handleCancel} footer={footer}>
                <h3 style={{ textAlign: 'center', fontSize: 24, margin: 40 }}>Semi Design New Features</h3>
                <List
                    dataSource={data}
                    split={false}
                    renderItem={(item) => (
                        <List.Item
                            header={item.icon}
                            main={
                                <div>
                                    <h6 style={{ margin: 0, fontSize: 16 }}>{item.title}</h6>
                                    <p style={{ marginTop: 4, color: 'var(--semi-color-text-1)' }}>{item.content}</p>
                                </div>
                            }
                        />
                    )}
                />
            </Modal>
        </>
    );
}

全屏 Modal

使用 fullScreen={true} 可以开启全屏对话框

代码
import { useState } from 'react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    const onClose = () => {
        setVisible(false);
    };
    return (
        <>
            <Button onClick={() => setVisible(true)}>打开全屏弹窗</Button>
            <Modal title="全屏对话框标题" fullScreen visible={visible} onOk={onClose} onCancel={onClose}>
                <p>This is a full screen modal</p>
                <p>More content...</p>
            </Modal>
        </>
    );
}

命令式调用

使用 confirm() 可以设置一个确认框。支持各种类型的信息提示。命令式调用也可以自定义 icon , 支持 string 和 ReactNode 类型。其他 Modal 支持的 props 都可以传入。











代码
import { IconSend } from '@fibrous/semi-icons-react';
import { Modal, Button } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    function success() {
        Modal.success({ title: 'This is a success message', content: 'bla bla bla...' });
    }

    function info() {
        Modal.info({ title: 'Here is some info', content: 'bla bla bla...' });
    }

    function error() {
        Modal.error({ title: 'Unfortunately, there is an error', content: 'bla bla bla...' });
    }

    function warning() {
        Modal.warning({ title: 'Warning: be cautious ahead', content: 'bla bla bla...' });
    }

    function confirm() {
        Modal.confirm({ title: 'Are you sure ?', content: 'bla bla bla...' });
    }

    function custom() {
        Modal.info({
            title: 'This is a custom modal',
            content: 'bla bla bla...',
            icon: <IconSend />,
            cancelButtonProps: { theme: 'borderless' },
            okButtonProps: { theme: 'solid' },
        });
    }

    return (
        <div>
            <Button onClick={info}>Info</Button>
            <br />
            <br />
            <Button onClick={success}>Success</Button>
            <br />
            <br />
            <Button onClick={error} type="danger">
                Error
            </Button>
            <br />
            <br />
            <Button onClick={warning} type="warning">
                Warning
            </Button>
            <br />
            <br />
            <Button onClick={confirm} type="primary">
                Confirm
            </Button>
            <br />
            <br />
            <Button onClick={custom}>Custom</Button>
        </div>
    );
}

Hooks 用法

通过 Modal.useModal 创建支持读取 context 的 contextHolder。

代码
import en_GB from '@fibrous/semi-foundation/locale/source/en_GB';
import { ConfigProvider, Button, Modal } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [modal, contextHolder] = Modal.useModal();
    const config = { title: 'This is a success message', content: 'Context consumer' };

    return (
        <ConfigProvider locale={en_GB}>
            <div>
                <Button
                    onClick={() => {
                        modal.confirm(config);
                    }}
                >
                    Confirm Modal
                </Button>
            </div>
            {contextHolder}
        </ConfigProvider>
    );
}

可拖拽 Modal

通过 modalRender 自定义渲染 Modal 内容,可拖拽 Modal 通过 DragMove 组件实现。

代码
import { useState } from 'react';
import { Button, Modal, DragMove } from '@fibrous/semi-ui-react';

export default function ModalDemo() {
    const [visible, setVisible] = useState(false);
    return (
        <div>
            <Button onClick={() => setVisible(true)}>Open Modal</Button>
            <Modal title="可拖拽Modal" visible={visible} centered onCancel={() => setVisible(false)} modalRender={(modal) => <DragMove positionStrategy="relative">{modal}</DragMove>}>
                <p>This is the content of a basic sidesheet.</p>
                <p>Here is more content...</p>
            </Modal>
        </div>
    );
}

API 参考

Props

属性说明类型默认值
afterClose对话框完全关闭后的回调;显示期间被卸载,或所在子树被 Activity 隐藏时也会调用一次。Type() => void-
bodyStyle对话框内容区的样式。CSSProperties-
cancelButtonProps取消按钮的属性,类型同 Button。打开后默认聚焦取消按钮,autoFocus 为 false 时不聚焦;onClick 先于内置的取消处理调用,不会替换内置处理。ButtonProps-
cancelLoading取消按钮是否加载中;不传时跟随 onCancel 返回的 Promise,显式传入 false 关闭该行为。boolean-
cancelText取消按钮文字,缺省取语言包 Modal.cancel。string-
centered是否垂直居中显示。booleanfalse
children对话框的正文。React.ReactNode-
className落在 portal 内最外层元素上的类名。string-
closable是否显示右上角的关闭按钮。booleantrue
closeIcon关闭按钮的图标;传入 null 时回落到默认图标,隐藏关闭按钮请用 closable={false}。ReactNode-
closeOnEsc是否允许按 Esc 取消对话框。booleantrue
confirmLoading确认按钮是否加载中;不传时跟随 onOk 返回的 Promise,显式传入 false 关闭该行为。boolean-
content组件版 Modal 不渲染该属性,对话框内容写在 children 中;它只用于 Modal.info 等命令式方法的选项。ReactNode-
direction文字方向,覆盖 ConfigProvider 的设置;不传时跟随所在位置的 ConfigProvider。'ltr' | 'rtl'-
footer完全替换默认页脚按钮。传入 null 时隐藏页脚区域。ReactNode-
footerFill默认页脚的两个按钮是否撑满排列,默认 false。boolean-
fullScreen是否全屏显示,开启后 width、height 不再生效。booleanfalse
getPopupContainer指定弹层渲染到的父级 DOM;不传时取 ConfigProvider 的 getPopupContainer,都没有时渲染到 document.body。自定义容器需要设置 position: relative,这会改变浮层的 DOM 位置,不改变视图位置。Type() => HTMLElement-
hasCancel默认页脚是否显示取消按钮。booleantrue
header完全替换默认头部(图标、标题与关闭按钮)。传入 null 时隐藏头部区域。ReactNode-
height对话框高度,数字按像素处理,字符串为合法 CSS 长度。string | number-
icon标题前的图标。ReactNode-
keepDOM关闭时是否保留对话框内部节点而不销毁。booleanfalse
lazyRender配合 keepDOM 使用;为 true 时,首次显示之前不渲染对话框。booleantrue
mask是否显示遮罩。booleantrue
maskClosable是否允许点击遮罩取消对话框。booleantrue
maskFixed遮罩限定在自定义容器内时,是否仍以 fixed 定位覆盖整个视口并按模态处理(aria-modal、页面 inert、Tab 锁定、body 滚动锁定)。booleanfalse
maskStyle遮罩的样式。CSSProperties-
modalContentClass对话框内容元素的类名。string-
modalRender自定义渲染对话框本身,参数是 role="dialog" 元素,返回值必须包含它,例如用 DragMove 包裹。Type(node: ReactNode) => ReactNode-
motion是否启用进出场动画。booleantrue
okButtonProps确认按钮的属性,类型同 Button。autoFocus 为 true 时打开后聚焦该按钮;onClick 先于内置的确认处理调用,不会替换内置处理。ButtonProps-
okText确认按钮文字,缺省取语言包 Modal.confirm。string-
okType确认按钮的类型,同 Button 的 type。OKType"primary"
onCancel取消按钮、关闭按钮、遮罩和 Esc 触发;按 Esc 时参数为原生 KeyboardEvent。返回 Promise 时取消按钮保持加载直到落定;对话框不会自行关闭,由使用方把 visible 设为 false。Type(e: React.MouseEvent | KeyboardEvent) => void | Promise<any>-
onOk点击确认按钮时调用,参数是点击事件;返回 Promise 时确认按钮保持加载直到落定。对话框不会自行关闭,由使用方把 visible 设为 false。Type(e: React.MouseEvent) => void | Promise<any>-
preventScroll组件内部调用 focus 时是否阻止浏览器滚动到被聚焦元素,不影响使用方自己的 focus 调用;未设置时聚焦会滚动到该元素。boolean-
ref接收 portal 内最外层 div 元素的引用,没有渲染内容时为 null。TypeReact.Ref<HTMLDivElement>-
role对话框元素的 role,默认 dialog;命令式方法使用 alertdialog。'dialog' | 'alertdialog'-
size对话框宽度档位:small 为 448px,medium 为 684px,large 为 920px,full-width 为 100vw - 64px。Size"small"
style落在 .semi-modal 对话框盒子上的样式。CSSProperties-
title对话框标题;未传入 aria-label 或自定义 header 时,标题用于命名对话框。ReactNode-
visible对话框是否可见,由使用方控制。booleanfalse
width对话框宽度,数字按像素处理,字符串为合法 CSS 长度;不传时由 size 决定。string | number-
zIndex弹层外层的 z-index。number1000

role 与全部 aria-* 属性落在 role="dialog" 元素上,style 落在 .semi-modal 对话框盒子上,className 与其他原生属性(如 id、data-*)落在 portal 内最外层元素上。

组件版 Modal 不渲染 content,对话框内容请写在 children 中;content 只用于下面的命令式方法。

  • Modal.info
  • Modal.success
  • Modal.error
  • Modal.warning
  • Modal.confirm
属性说明类型默认值
bodyStyle对话框内容的样式CSSProperties无
cancelButtonProps取消按钮的 propsButtonProps无
cancelText取消按钮的文字string无
centered是否居中显示booleanfalse
className可用于设置样式类名string无
closable是否显示右上角的关闭按钮booleantrue
confirmLoading确认按钮 loading;未设置时跟随 onOk 返回 Promise 的 pending 状态,显式传 false 关闭该行为boolean-
content对话框内容ReactNode无
footer对话框底部ReactNode无
footerFill底部按钮是否撑满booleanfalse
header对话框头部ReactNode无
height高度string | number无
icon自定义 iconReactNode-
mask是否显示遮罩booleantrue
maskClosable是否允许通过点击遮罩来关闭对话框booleantrue
maskStyle遮罩的样式CSSProperties无
modalContentClass可用于设置对话框内容的样式类名string无
modalRender自定义渲染 Modal(modal: ReactNode) => ReactNode-
motion动画效果开关,update 中修改同样生效booleantrue
okButtonProps确认按钮的 props,其中的 onClick 先于内置处理调用,不会替换内置处理ButtonProps无
okText确认按钮的文字string无
okType确认按钮的类型stringprimary
style可用于设置样式CSSProperties无
title对话框的标题ReactNode无
width宽度,未设置时由 size 决定(small 为 448)string | number-
zIndex遮罩的 z-index 值number1000
onCancel取消回调,返回 promise 时 resolve 后自动关闭;按 Esc 关闭时参数为原生 KeyboardEvent(e: React.MouseEvent | KeyboardEvent) => void | Promise<any>无
onOk点击确定回调,参数是点击事件,返回 promise 时 resolve 后自动关闭(e: any) => void | Promise<any>无

以上函数调用后,会返回一个引用,可以通过该引用更新和关闭弹窗。update 接收与以上函数相同的属性(ModalProps),合并到当前配置,不接收 type。

const modal = Modal.info();

modal.update({
  title: '更新的标题',
  content: '更新的内容',
});

modal.destroy();
  • Modal.destroyAll

使用 Modal.destroyAll() 可以销毁命令式及以上.info()等创建的弹窗。

  • Modal.useModal 当你需要使用 Context 时,可以通过 Modal.useModal 创建一个 contextHolder 插入相应的节点中。此时通过 hooks 创建的 Modal 将会得到 contextHolder 所在位置的所有上下文。创建的 modal 对象拥有与 Modal.method 相同的创建通知方法。

Accessibility

ARIA

WAI-ARIA: https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/

  • 组件版 Modal 的 role 为 dialog,遵循 APG Dialog (Modal)
  • 确认框(Modal.confirm、info、success、warning、error,以及 useModal 的同名方法)的 role 为 alertdialog,aria-describedby 指向正文,遵循 APG Alert Dialog
  • aria-modal 在对话框是模态时设置为 true。模态的判定是:有遮罩(mask),且挂载在 body 中(以实际容器判断,ConfigProvider 的 getPopupContainer 同样计入)或设置了 maskFixed。mask={false},或遮罩限定在自定义容器内时背景保持可用,不输出 aria-modal
  • aria-labelledby 对应对话框标题;传入 aria-label 或自定义头部时不生成该引用
  • 组件版 Modal 默认不设置 aria-describedby:正文含表单、列表或多段内容时,整段正文被读出反而干扰;需要时由使用方传入
  • 使用方传入的 role 与全部 aria-* 属性落在 role 所在的元素上
  • 关闭按钮的 aria-label 来自当前语言包(简体中文为「关闭」,英文为 'Close')

键盘和焦点

  • Modal 在弹出时自动获得焦点。对话框内带 autoFocus(Vue 中为 autofocus)的元素优先获得焦点,没有时默认聚焦到取消按钮,可通过在 cancelButtonProps 或 okButtonProps 传入 autoFocus 来控制该行为。keepDOM 时再次打开,结果相同;keepDOM 加 lazyRender={false} 且初始隐藏时,autoFocus 元素在 display: none 下无法获得焦点,之后的打开落到默认按钮。
  • 模态对话框关闭时,焦点自动回归到打开前元素。键盘用户可以使用 Tab 键和 Shift + Tab,将焦点在 Modal 内循环移动,包括 Modal 自带的关闭按钮和确定取消按钮,此时 Modal 背后的页面不可交互,也不可被 tab 聚焦。
  • 非模态对话框(mask={false},或遮罩限定在自定义容器内且未设置 maskFixed)打开时同样移入焦点,但不锁定 Tab,页面其余部分保持可用。关闭时只在焦点仍在对话框内或已落到 body 时归还,用户已移到页面其他位置的焦点不动。挂载在 body 中且 mask={false} 的 Modal 不锁定 body 滚动。
  • 修改 closeOnEsc 默认值为 true,允许用户通过键盘直接关闭 Modal 带来更好的体验

文案规范

  • 命令式 Modal 与 默认 Modal 两种模态对话框的标题使用 动词 + 名词 的格式,无论是陈述句还是问句
✅ 推荐用法❌ 不推荐用法
Edit ticketEdit
Delete form?Are you sure you want to delete form?
  • 两种模态对话框的操作按钮在保证标题描述清楚的前提下,只需要使用标题内的动词即可
✅ 推荐用法❌ 不推荐用法
EditEdit ticket
  • 命令式 Modal 的正文规范
    • 对标题进行具体的解释说明,不要重复标题的信息
    • 确保用户知道在必要时如何采取行动

设计变量

下表是组件内部的 Sass 变量,不能覆写。定制样式请覆写 --semi-* CSS 变量(见 Design Token 页),或写不分层的 CSS 规则。
Sass 变量值用法
$animation_duration-modal-show120ms弹窗打开-动画持续时间
$animation_function-modal-showcubic-bezier(0.215, 0.61, 0.355, 1)弹窗打开-过渡曲线
$animation_delay-modal-show0ms弹窗打开-延迟时间
$animation_duration-modal-hide120ms弹窗关闭-动画持续时间
$animation_function-modal-hidecubic-bezier(0.215, 0.61, 0.355, 1)弹窗关闭-过渡曲线
$animation_delay-modal-hide0ms弹窗关闭-延迟时间
$animation_duration-modal_mask-show90ms弹窗打开时-蒙层颜色-动画持续时间
$animation_function-modal_mask-showcubic-bezier(0.215, 0.61, 0.355, 1)弹窗打开时-蒙层颜色-过渡曲线
$animation_delay-modal_mask-show0ms弹窗打开时-蒙层颜色-延迟时间
$animation_duration-modal_mask-hide90ms弹窗关闭时-蒙层颜色-动画持续时间
$animation_function-modal_mask-hidecubic-bezier(0.215, 0.61, 0.355, 1)弹窗关闭时-蒙层颜色-过渡曲线
$animation_delay-modal_mask-hide0ms弹窗关闭时-蒙层颜色-延迟时间
$animation_transform_scale-modal_content-open0.7弹窗打开时-缩放比例
$animation_opacity-modal_content-open0弹窗打开时-起始透明度
$animation_transform_scale-modal_content-close0.7弹窗关闭时-缩放比例
$animation_opacity-modal_content-close0弹窗关闭时-起始透明度
$animation_opacity-modal_mask-open0弹窗打开时-蒙层起始透明度
$animation_opacity-modal_mask-close0弹窗关闭时-蒙层起始透明度
$color-modal-bgvar(--semi-color-bg-2)模态框背景颜色
$color-modal_mask-bgvar(--semi-color-overlay-bg)模态框蒙层颜色
$color-modal_main-textvar(--semi-color-text-0)模态框文字颜色
$color-modal_info-iconvar(--semi-color-info)模态框信息图标颜色
$color-modal_primary-iconvar(--semi-color-primary)模态框主要图标颜色
$color-modal_success-iconvar(--semi-color-success)模态框成功图标颜色
$color-modal_danger-iconvar(--semi-color-danger)模态框危险图标颜色
$color-modal_warning-iconvar(--semi-color-warning)模态框警告图标颜色
$color-modal_content-bordervar(--semi-color-border)模态框描边颜色
$color-modal_header-bgtransparent模态框 header 背景填充色
$color-modal_footer-bgtransparent模态框 footer 背景填充色
$spacing-modal-marginY80px模态框距容器顶部外边距
$spacing-modal-marginXauto模态框水平外边距(默认居中)
$spacing-modal_mask-top0模态框蒙层顶部位置
$spacing-modal_mask-right0模态框蒙层右侧位置
$spacing-modal_mask-bottom0模态框蒙层底部位置
$spacing-modal_mask-left0模态框蒙层左侧位置
$spacing-modal_content_withicon-marginLeft36px模态框蒙层左侧位置
$spacing-modal_icon_wrapper-marginRight$spacing-base-tight模态框图标右侧外边距
$spacing-modal_wrap-top0
$spacing-modal_wrap-right0
$spacing-modal_wrap-bottom0
$spacing-modal_wrap-left0
$spacing-modal_title-margin0模态框标题外边距
$spacing-modal_content-paddingY0模态框内容垂直内边距
$spacing-modal_content-paddingX24px模态框内容水平内边距
$spacing-modal_header-marginY24px模态框标题垂直外边距
$spacing-modal_header-marginX0模态框标题水平外边距
$spacing-modal_header-paddingY0
$spacing-modal_header-paddingX0
$spacing-modal_body_wrapper-marginY24px
$spacing-modal_body_wrapper-marginX0
$spacing-modal_body-margin0模态框 body 外边距
$spacing-modal_body-padding0模态框 内容外Padding
$spacing-modal_footer-marginY24px模态框 footer 垂直外边距
$spacing-modal_footer-marginX0模态框 footer 水平外边距
$spacing-modal_footer-paddingY0
$spacing-modal_footer-paddingX0
$spacing-modal_footer_button-marginLeft$spacing-base-tight模态框 footer 按钮左侧外边距
$spacing-modal_confirm_header-marginBottom8px命令式调用模态框 header 底部外边距
$spacing-modal_confirm_icon_wrapper-marginRight$spacing-base-tight命令式调用模态框图标右侧外边距
$spacing-modal_content_fullscreen-top0px模态框内容全屏顶部位置
$width-modal_title100%模态框标题宽度
$width-modal_content100%模态框内容宽度
$height-modal_contentmax-content模态框内容高度
$width-modal_content-border1px模态框内容描边宽度
$width-modal_small448px模态框宽度 - 小
$width-modal_medium684px模态框宽度 - 中
$width-modal_large920px模态框宽度 - 大
$width-modal_full_widthcalc(100vw - 64px)模态框宽度 - 全屏
$radius-modal_contentvar(--semi-border-radius-large)模态框圆角大小
$radius-modal_content_fullscreen0模态框圆角大小 - 全屏
$radius-modal_footer0 0 5px 5px模态框 footer 圆角大小
$font-modal_header-fontSize$font-size-regular模态框 title 字号
$font-modal_header-fontWeight$font-weight-bold模态框 title 字重
$color-modal_header-bordertransparent模态框 header 底部描边颜色
$width-modal_header-border0模态框 header 底部描边宽度
$color-modal_footer-bordertransparent模态框 footer 顶部描边颜色
$width-modal_footer-border0模态框 footer 顶部描边宽度
$shadow-modal_contentvar(--semi-shadow-elevated)
$filter-modal_mask-bgnone
$filter-modal_content-bgnone

FAQ

  • 为什么使用 LocaleProvider 后, Modal.confirm 确认、取消按钮的文本没有国际化?

    Modal 使用 Portal 将浮层节点插入到 DOM 树中。但这个操作仅能改变节点在 DOM 树中的位置,无法改变节点在 React 节点树中的位置,LocalProvider是基于 Context 机制传递的,必须是从属的 React 子结点才可消费到 Local 相关 Context。因此命令式的 Modal 的内置文本无法自动适配国际化。你可以通过 okText 和 cancelText 这两个属性来根据 Locale 重新设置 i18 的文本。
    你也可以通过 Modal.useModal 方法来返回 modal 实体以及 contextHolder 节点。将 contextHolder 插入到你需要获取 context 位置,即可使 Modal 获取到对应的 Context,如 ConfigProvider 或者 LocaleProvider 的配置。

  • 为什么 title 和 content 的间距在命令式调用和非命令式调用下不同?

    命令式调用场景下,标题和内容的相关性更强,所以用更近的距离表达这种强相关性,符合预期。用户如果不想要这种效果,可以自己做样式覆盖。