Skip to content

Dialog 对话框 ​

新粗野主义风格的模态对话框,基于 reka-ui 的 Dialog 原语构建。支持遮罩层、关闭按钮和可组合的子组件。

预览 ​

Preview

安装 ​

pnpm dlx brutx-vue@latest add dialog

用法 ​

vue
<script setup>
import { DialogRoot as Dialog, DialogTrigger, DialogClose } from 'reka-ui'
import { DialogContent, DialogHeader, DialogFooter, DialogTitle, DialogDescription } from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
</script>

<template>
    <Dialog>
        <DialogTrigger as-child>
            <Button variant="primary">Open Dialog</Button>
        </DialogTrigger>
        <DialogContent>
            <DialogHeader>
                <DialogTitle>Edit Profile</DialogTitle>
                <DialogDescription>
                    Make changes to your profile here. Click save when you're done.
                </DialogDescription>
            </DialogHeader>
            <DialogFooter>
                <DialogClose as-child>
                    <Button variant="outline">Cancel</Button>
                </DialogClose>
                <Button variant="primary">Save</Button>
            </DialogFooter>
        </DialogContent>
    </Dialog>
</template>

尺寸 ​

通过 DialogContent 的 size 属性控制对话框的最大宽度。默认值为 default(max-w-lg)。

尺寸最大宽度适用场景
smmax-w-sm确认框、简单提示
defaultmax-w-lg标准表单、常规内容
lgmax-w-2xl多列表单、详细设置
xlmax-w-4xl复杂内容、数据展示
fullmax-w-[calc(100vw-2rem)]大幅内容、全屏式交互
vue
<script setup>
import { DialogRoot as Dialog, DialogTrigger } from 'reka-ui'
import { DialogContent, DialogHeader, DialogTitle, DialogDescription } from 'brutx-ui-vue'
import { Button } from 'brutx-ui-vue'
</script>

<template>
    <Dialog>
        <DialogTrigger as-child>
            <Button variant="primary">打开小型对话框</Button>
        </DialogTrigger>
        <DialogContent size="sm">
            <DialogHeader>
                <DialogTitle>确认删除</DialogTitle>
                <DialogDescription>此操作不可撤销,确定要继续吗?</DialogDescription>
            </DialogHeader>
        </DialogContent>
    </Dialog>
</template>

子组件 ​

组件说明
Dialog根组件(需从 reka-ui 导入:import { DialogRoot as Dialog } from 'reka-ui')
DialogTrigger打开对话框的按钮(需从 reka-ui 导入:import { DialogTrigger } from 'reka-ui')
DialogContent带遮罩层的对话框内容面板
DialogHeader头部容器
DialogFooter底部容器,弹性布局
DialogTitle对话框标题
DialogDescription对话框描述文本
DialogClose关闭按钮(需从 reka-ui 导入:import { DialogClose } from 'reka-ui')
DialogOverlay背景遮罩层
DialogPortal传送门容器(需从 reka-ui 导入:import { DialogPortal } from 'reka-ui')
DialogEnhanced支持可拖拽和可调整大小的增强版对话框

DialogEnhanced 用法 ​

支持可拖拽和可调整大小的增强版对话框:

vue
<script setup>
import { DialogRoot as Dialog, DialogTrigger } from 'reka-ui'
import { DialogEnhanced, DialogHeader, DialogTitle } from 'brutx-ui-vue'
</script>

<template>
    <Dialog>
        <DialogTrigger>打开可拖拽对话框</DialogTrigger>
        <DialogEnhanced
            draggable
            resizable
            :min-width="300"
            :min-height="200"
            drag-handle=".dialog-header"
        >
            <DialogHeader class="dialog-header">
                <DialogTitle>可拖拽对话框</DialogTitle>
            </DialogHeader>
            <p>拖拽标题栏移动,拖拽边缘调整大小</p>
        </DialogEnhanced>
    </Dialog>
</template>

API 参考 ​

DialogContent

DialogContent — 属性
名称类型默认值说明
showCloseButton
boolean | undefined
true
控制内容面板右上角的内置关闭按钮是否渲染。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
true

来源

DialogContent.vue:22

packages/ui/src/components/dialog/DialogContent.vue

size
"default" | "full" | "lg" | "sm" | "xl" | undefined
"default"
设置对话框内容面板的宽度变体。
详情

声明类型

NonNullable<"default" | "lg" | "sm" | "xl" | "full" | null | undefined> | undefined

字面量

  • "default"
  • "full"
  • "lg"
  • "sm"
  • "xl"

默认值详情

解析值
"default"

来源

DialogContent.vue:23

packages/ui/src/components/dialog/DialogContent.vue

entrance
"fade-zoom" | "shutter" | undefined
"fade-zoom"
选择内容面板的入场动效变体。
详情

声明类型

NonNullable<"fade-zoom" | "shutter" | null | undefined> | undefined

字面量

  • "fade-zoom"
  • "shutter"

默认值详情

解析值
"fade-zoom"

来源

DialogContent.vue:25

packages/ui/src/components/dialog/DialogContent.vue

forceMount
boolean | undefined
undefined
将挂载保持策略传递给遮罩层和内容原语,以便在关闭状态下仍保持挂载。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
undefined

来源

DialogContent.vue:26

packages/ui/src/components/dialog/DialogContent.vue

class
string | undefined
undefined
追加到对话框内容面板的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

DialogContent.vue:27

packages/ui/src/components/dialog/DialogContent.vue

DialogContent — 插槽
名称签名或类型说明
#default
{}
渲染对话框的主体内容;内置关闭按钮会放在插槽内容之后。
详情

声明类型

{}

来源

DialogContent.vue

packages/ui/src/components/dialog/DialogContent.vue

DialogDescription

DialogDescription — 属性
名称类型默认值说明
class
string | undefined
—
追加到描述元素的自定义 CSS 类;其余属性(例如 id)通过属性透传交给 Reka UI 原语。
详情

声明类型

string | undefined

默认值详情

未声明默认值
—

来源

DialogDescription.vue:7

packages/ui/src/components/dialog/DialogDescription.vue

DialogDescription — 插槽
名称签名或类型说明
#default
{}
对话框的辅助说明内容。
详情

声明类型

{}

来源

DialogDescription.vue

packages/ui/src/components/dialog/DialogDescription.vue

DialogEnhanced

DialogEnhanced — 属性
名称类型默认值说明
draggable
boolean | undefined
false
启用内容面板的指针拖拽移动;全屏模式下不应用拖拽移动样式。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogEnhanced.vue:19

packages/ui/src/components/dialog/DialogEnhanced.vue

dragHandle
string | HTMLElement | undefined
undefined
将拖拽起点限制为 CSS 选择器匹配的后代元素或指定 HTMLElement。
详情

声明类型

string | HTMLElement | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:20

packages/ui/src/components/dialog/DialogEnhanced.vue

bounds
"viewport" | "parent" | { top: number; left: number; right: number; bottom: number; } | undefined
"viewport"
限制拖拽位置到父容器、视口,或给定的 top、left、right、bottom 边界。
详情

声明类型

"viewport" | "parent" | { top: number; left: number; right: number; bottom: number; } | undefined

字面量

  • "parent"
  • "viewport"

默认值详情

解析值
"viewport"

来源

DialogEnhanced.vue:21

packages/ui/src/components/dialog/DialogEnhanced.vue

initialPosition
{ x: number; y: number; } | undefined
undefined
为几何状态控制器提供初始 x、y 坐标。
详情

声明类型

{ x: number; y: number; } | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:22

packages/ui/src/components/dialog/DialogEnhanced.vue

resizable
boolean | undefined
false
启用对话框边缘的指针缩放交互。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogEnhanced.vue:23

packages/ui/src/components/dialog/DialogEnhanced.vue

minWidth
number | undefined
200
设置缩放时允许的最小宽度,单位为像素。
详情

声明类型

number | undefined

默认值详情

解析值
200

来源

DialogEnhanced.vue:24

packages/ui/src/components/dialog/DialogEnhanced.vue

minHeight
number | undefined
150
设置缩放时允许的最小高度,单位为像素。
详情

声明类型

number | undefined

默认值详情

解析值
150

来源

DialogEnhanced.vue:25

packages/ui/src/components/dialog/DialogEnhanced.vue

maxWidth
number | undefined
undefined
设置缩放时可选的最大宽度,单位为像素。
详情

声明类型

number | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:26

packages/ui/src/components/dialog/DialogEnhanced.vue

maxHeight
number | undefined
undefined
设置缩放时可选的最大高度,单位为像素。
详情

声明类型

number | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:27

packages/ui/src/components/dialog/DialogEnhanced.vue

aspectRatio
number | undefined
undefined
提供锁定的宽高比,由几何状态控制器用于调整尺寸。
详情

声明类型

number | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:28

packages/ui/src/components/dialog/DialogEnhanced.vue

showCloseButton
boolean | undefined
true
控制增强对话框内容面板中的内置关闭按钮是否渲染。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
true

来源

DialogEnhanced.vue:29

packages/ui/src/components/dialog/DialogEnhanced.vue

forceMount
boolean | undefined
undefined
要求遮罩层及内容在关闭状态仍保持挂载;此策略优先于 destroyOnClose。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:30

packages/ui/src/components/dialog/DialogEnhanced.vue

fullscreen
boolean | undefined
false
将内容面板固定为占满视口的全屏布局,并忽略拖动几何样式。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogEnhanced.vue:32

packages/ui/src/components/dialog/DialogEnhanced.vue

beforeClose
(() => boolean | Promise<boolean>) | undefined
undefined
关闭请求前执行的同步或异步校验;返回 false 或抛出/reject 时不会发出关闭事件。
详情

声明类型

(() => boolean | Promise<boolean>) | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:34

packages/ui/src/components/dialog/DialogEnhanced.vue

destroyOnClose
boolean | undefined
false
关闭后延迟卸载默认插槽内容;forceMount 为真时不会卸载。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogEnhanced.vue:36

packages/ui/src/components/dialog/DialogEnhanced.vue

destroyDelay
number | undefined
300
destroyOnClose 启用时,关闭后等待卸载插槽内容的毫秒数。
详情

声明类型

number | undefined

默认值详情

声明
DEFAULT_DIALOG_TRANSITION_MS

来源: packages/ui/src/components/dialog/DialogEnhanced.vue

解析值
300

来源

DialogEnhanced.vue:38

packages/ui/src/components/dialog/DialogEnhanced.vue

zIndex
number | undefined
undefined
显式设置对话框内容面板的 CSS z-index。
详情

声明类型

number | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:40

packages/ui/src/components/dialog/DialogEnhanced.vue

class
string | undefined
undefined
追加到对话框内容面板的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

DialogEnhanced.vue:41

packages/ui/src/components/dialog/DialogEnhanced.vue

DialogEnhanced — 事件
名称签名或类型说明
@open
[]
组件挂载时发出,表示 DialogEnhanced 实例已挂载,不表示受控打开状态每次变化。
详情

声明类型

[]

来源

DialogEnhanced.vue

packages/ui/src/components/dialog/DialogEnhanced.vue

@close
[]
关闭请求未被 beforeClose 拒绝时发出;未提供钩子时关闭请求直接通过。
详情

声明类型

[]

来源

DialogEnhanced.vue

packages/ui/src/components/dialog/DialogEnhanced.vue

@update:open
[value: boolean]
已接受的关闭请求以 false 发出,用于将 DialogRoot 的受控打开状态设为关闭。
详情

声明类型

[value: boolean]

字面量

  • false
  • true

来源

DialogEnhanced.vue

packages/ui/src/components/dialog/DialogEnhanced.vue

DialogEnhanced — 插槽
名称签名或类型说明
#default
{}
对话框内容;启用 destroyOnClose 后可在关闭延迟结束时卸载。
详情

声明类型

{}

来源

DialogEnhanced.vue

packages/ui/src/components/dialog/DialogEnhanced.vue

DialogFooter

DialogFooter — 属性
名称类型默认值说明
class
string | undefined
—
追加到底部操作区域的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

未声明默认值
—

来源

DialogFooter.vue:7

packages/ui/src/components/dialog/DialogFooter.vue

DialogFooter — 插槽
名称签名或类型说明
#default
{}
底部操作内容;没有默认插槽内容时 Footer 容器不渲染。
详情

声明类型

{}

来源

DialogFooter.vue

packages/ui/src/components/dialog/DialogFooter.vue

DialogHeader

DialogHeader — 属性
名称类型默认值说明
class
string | undefined
—
追加到标题区域容器的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

未声明默认值
—

来源

DialogHeader.vue:7

packages/ui/src/components/dialog/DialogHeader.vue

DialogHeader — 插槽
名称签名或类型说明
#default
{}
标题、描述或其他头部内容。
详情

声明类型

{}

来源

DialogHeader.vue

packages/ui/src/components/dialog/DialogHeader.vue

DialogOverlay

DialogOverlay — 属性
名称类型默认值说明
class
string | undefined
undefined
追加到背景遮罩原语的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

解析值
undefined

来源

DialogOverlay.vue:9

packages/ui/src/components/dialog/DialogOverlay.vue

forceMount
boolean | undefined
undefined
将 force-mount 策略传递给 Reka UI 遮罩原语。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
undefined

来源

DialogOverlay.vue:11

packages/ui/src/components/dialog/DialogOverlay.vue

asChild
boolean | undefined
false
将遮罩原语的元素渲染委托给默认插槽中的子元素。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogOverlay.vue:12

packages/ui/src/components/dialog/DialogOverlay.vue

pattern
boolean | undefined
false
为遮罩层添加点阵半色调背景纹理。
详情

声明类型

boolean | undefined

字面量

  • false
  • true

默认值详情

解析值
false

来源

DialogOverlay.vue:14

packages/ui/src/components/dialog/DialogOverlay.vue

DialogOverlay — 插槽
名称签名或类型说明
#default
{}
为 asChild 模式提供要渲染的遮罩子元素。
详情

声明类型

{}

来源

DialogOverlay.vue

packages/ui/src/components/dialog/DialogOverlay.vue

DialogTitle

DialogTitle — 属性
名称类型默认值说明
class
string | undefined
—
追加到对话框标题原语的自定义 CSS 类。
详情

声明类型

string | undefined

默认值详情

未声明默认值
—

来源

DialogTitle.vue:7

packages/ui/src/components/dialog/DialogTitle.vue

DialogTitle — 插槽
名称签名或类型说明
#default
{}
对话框的标题文本或内容。
详情

声明类型

{}

来源

DialogTitle.vue

packages/ui/src/components/dialog/DialogTitle.vue

Reka UI 原语 ​

DialogRoot、DialogTrigger、DialogClose 和 DialogPortal 是示例中直接从 reka-ui 导入的原语;DialogContent、DialogHeader、DialogFooter、DialogTitle、DialogDescription、DialogOverlay 和 DialogEnhanced 是 BrutxUI 组件。DialogEnhanced 需要放在 DialogRoot 提供的上下文中使用。

可访问性 ​

  • 键盘操作:按 Escape 关闭对话框
  • 焦点管理:对话框打开时,焦点被限制在对话框内;关闭时恢复焦点
  • ARIA 属性:关闭按钮包含屏幕阅读器文本
  • 交互元素:拖拽时自动排除交互元素(Input、Button 等)

函数式 API ​

除了声明式组件,Dialog 还提供命令式调用与 Composable 方式,适合在业务逻辑中快速弹出自定义对话框容器。如需结构化确认框、状态图标或输入提示,请参阅独立的 MessageBox 消息对话框。

showDialog ​

调用 showDialog 以命令式挂载通用的 Dialog 对话框容器:

ts
import { showDialog } from 'brutx-ui-vue'

const instance = showDialog({
    title: '系统设置',
    content: '自定义弹层正文内容...',
    size: 'default',
    draggable: true,
    showCloseButton: true,
    onCancel: () => {
        console.log('对话框已关闭')
    },
})

// 手动关闭
// instance.close()

常用参数:

参数类型默认值说明
titlestring—对话框标题
descriptionstring—对话框描述
contentstring | Component | VNode | (() => ...)—自定义正文内容
footerstring | Component | VNode | (() => ...)—自定义底部插槽内容
size'sm' | 'default' | 'lg' | 'xl' | 'full''default'对话框尺寸
draggablebooleanfalse是否开启拖拽
resizablebooleanfalse是否开启缩放
fullscreenbooleanfalse是否全屏展示
zIndexnumber—自定义弹层层级
onCancel() => void—关闭时的回调钩子

返回值: OverlayInstanceHandle<void> — 包含 close()、destroy() 方法及 promise 句柄。

useDialog(Composable) ​

在组件中使用 useDialog 组合式函数,获得响应式的状态与单例实例管理:

vue
<script setup>
import { useDialog } from 'brutx-ui-vue'

const { show, close, isOpen } = useDialog()

function showMyDialog() {
    show({
        title: '提示',
        content: '这是一个通过 Composable 打开的自定义对话框',
    })
}
</script>

<template>
    <div class="flex items-center gap-3">
        <button @click="showMyDialog">打开对话框</button>
        <span v-if="isOpen" class="text-sm font-bold text-brutal-accent">对话框开启中</span>
    </div>
</template>

TIP

useDialog 返回的 isOpen 属性为 Readonly<Ref<boolean>> 只读响应式视图,状态仅由 Composable 内部统一调度。

useDialogGeometry(空间几何状态控制器) ​

当需要对自定义弹窗或浮层实现拖拽、缩放与边界约束时,可直接使用底层的 useDialogGeometry 纯空间几何状态控制器:

ts
import { useDialogGeometry } from 'brutx-ui-vue'

const {
    contentRef,
    position,
    size,
    contentStyle,
    isDragging,
    isResizing,
    onDragStart,
    onResizeStart,
} = useDialogGeometry({
    draggable: true,
    resizable: true,
    bounds: 'viewport',
    minWidth: 320,
    minHeight: 240,
})
  • 纯空间几何职责:专注管理位置、尺寸、拖拽、缩放、宽高比与视口/父级边界限制,彻底与业务关闭控制流解耦;
  • 只读视图契约:position 与 size 为只读 Ref,程序化改写请通过 setPosition 与 setSize。

常见问题 ​

Q: 打开对话框后页面还能滚动怎么办?

A: 默认情况下 Dialog 的 modal 属性为 true,打开时会锁定背景滚动。如果遇到背景仍可滚动的情况,请确认没有通过 CSS 手动覆盖了 overflow 属性,或者检查是否有其他全局样式干扰了对话框的遮罩层行为。

Q: 如何通过代码控制对话框的打开和关闭?

A: 使用受控模式:将 Dialog 的 open 属性绑定到一个 ref 变量,然后通过修改该变量来控制对话框状态。也可以监听 update:open 事件来响应对话框的关闭操作(如按 Escape 键或点击遮罩层)。

Q: DialogEnhanced 的拖拽区域不正确,怎样设置拖拽手柄?

A: 通过 drag-handle 属性指定拖拽手柄,可以是 CSS 选择器字符串(如 ".dialog-header")或 DOM 元素引用。确保选择器能正确匹配到对话框内的某个元素,只有按住该元素区域才能拖拽。不设置时,默认整个对话框内容区域可拖拽。

蛮力铸就。