Dialog
Used to inform the user and carry out related operations while preserving the state of the current page.
This component internally integrates TuiMask to handle mask layer logic and is built upon the TuiTyped component, offering a powerful multi-tone and appearance system that flexibly adapts to various UI styles.
Basic Usage
The Dialog pops up a conversation box, suitable for scenarios requiring greater customization.
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
<template>
<TuiButton @click="visible = true">Open Regular Dialog</TuiButton>
<TuiDialog
v-model="visible"
title="Regular Title"
>
<div class="dialog-content">
This is basic content.
</div>
</TuiDialog>
</template>Layout and Size
Provides a rich set of properties to control the display position and size of the popup, supporting both percentages and pixel values.
- width: Customize width (supports
40%or300pixel values). - fullscreen: Enables full-screen display.
- alignCenter: Displays the popup centered vertically and horizontally (defaults to a top offset of
15vh). - top: Customize the distance from the top.
<script setup>
import { reactive } from 'vue'
const state = reactive({
showFull: false,
showCenter: false,
showCustom: false
})
</script>
<template>
<div class="demo-box">
<TuiButton @click="state.showFull = true">Full Screen</TuiButton>
<TuiButton @click="state.showCenter = true">Centered</TuiButton>
<TuiButton @click="state.showCustom = true">Custom Width and Top</TuiButton>
</div>
<TuiDialog v-model="state.showFull" title="Full Screen" fullscreen>
Content Area
</TuiDialog>
<TuiDialog v-model="state.showCenter" title="Centered" alignCenter width="30%">
Content area centered vertically
</TuiDialog>
<TuiDialog
v-model="state.showCustom"
title="Custom Style"
width="40%"
top="200"
>
Width 40%, 200px from the top
</TuiDialog>
</template>Dragging and Positioning
Dragging functionality can be implemented via the draggable property.
- draggable: Whether dragging is enabled.
- positionType: Defines the positioning strategy; options include
transform(recommended for better performance),absolute, andfixed. - dragContainment: Restricts the dragging range to within the visible area.
- resetDragOnClose: Whether to reset the position after closing.
<script setup>
import { ref } from 'vue'
const visible = ref(false)
</script>
<template>
<TuiButton @click="visible = true">Open Draggable Dialog</TuiButton>
<TuiDialog
v-model="visible"
title="Hold the title to drag me"
draggable
positionType="transform"
:resetDragOnClose="true"
>
<div>I use transform positioning for smoother dragging.</div>
</TuiDialog>
</template>Tones and Styles
TuiDialog deeply integrates the TuiTyped component. Using the type and typedConfig properties, you can easily configure the popup's theme tones (e.g., Primary, Warning, Danger) and visual styles (e.g., Transparent, Blur background, Strong/Weak tones).
About TuiTyped: This is an underlying atomic component specifically for handling component tone variants and visual depth. It allows components to automatically calculate the optimal foreground and background colors across different backgrounds.
Common Tones
Quickly switch preset semantic colors via the type property.
<script setup>
import { reactive } from 'vue'
const dialogs = reactive({
primary: false,
success: false,
warning: false,
danger: false
})
</script>
<template>
<div class="demo-gap">
<TuiButton type="primary" @click="dialogs.primary = true">Primary</TuiButton>
<TuiButton type="success" @click="dialogs.success = true">Success</TuiButton>
<TuiButton type="warning" @click="dialogs.warning = true">Warning</TuiButton>
<TuiButton type="danger" @click="dialogs.danger = true">Danger</TuiButton>
</div>
<TuiDialog v-model="dialogs.primary" title="Primary" type="primary">Content</TuiDialog>
<TuiDialog v-model="dialogs.success" title="Success" type="success">Content</TuiDialog>
<TuiDialog v-model="dialogs.warning" title="Warning" type="warning">Content</TuiDialog>
<TuiDialog v-model="dialogs.danger" title="Danger" type="danger">Content</TuiDialog>
</template>Advanced Style Configuration (TypedConfig)
Through the typedConfig object, you can control fine-grained visual expressions, such as tone intensity (tone) and transparency (transparent).
<script setup>
import { ref } from 'vue'
const visible = ref(false)
const glassConfig = {
transparent: true, // Enable semi-transparency
backgroundBlur: true, // Enable background blur
tone: 'strong' // Strong tone mode
}
</script>
<template>
<TuiButton @click="visible = true">Open Frosted Glass Style</TuiButton>
<TuiDialog
v-model="visible"
title="Advanced Style"
type="primary"
:typedConfig="glassConfig"
>
This is a Dialog with background blur and semi-transparency effects.
</TuiDialog>
</template>Nesting and Multiple Levels
Opening one Dialog inside another is supported. TuiDialog automatically handles the hierarchy.
<script setup>
import { reactive } from 'vue'
const state = reactive({
outer: false,
inner: false
})
const handleOpenInner = () => {
state.inner = true
}
</script>
<template>
<TuiButton @click="state.outer = true">Open First Level</TuiButton>
<TuiDialog v-model="state.outer" title="First Level Dialog" width="40%">
<div class="dialog-content">
<p>Click the button below to open the nested second level.</p>
<TuiButton @click="handleOpenInner">Open Second Level</TuiButton>
</div>
</TuiDialog>
<TuiDialog v-model="state.inner" title="Second Level Dialog" width="20%">
<div class="dialog-content">
This is the topmost popup content.
</div>
</TuiDialog>
</template>API Reference
Props
| Property | Description | Type | Default |
|---|---|---|---|
| modelValue | (v-model) Whether to show the Dialog | Boolean | false |
| title | Title text | String | — |
| width | Popup width; supports 300 (px) or '40%' | String / Number | null |
| top | Offset from the top | String / Number | — |
| alignCenter | Whether to center vertically | Boolean | false |
| center | Whether to center the Header and Content inside the popup | Boolean | false |
| fullscreen | Whether to display in full screen | Boolean | false |
| modal | Whether a mask layer is required | Boolean | true |
| draggable | Whether to enable header dragging | Boolean | false |
| positionType | Drag positioning type; options: `'transform' | 'absolute' | 'fixed'` |
| dragContainment | Whether to restrict dragging to the window range | Boolean | true |
| resetDragOnClose | Whether to reset the drag position when closing | Boolean | true |
| type | Semantic type; options: `'default' | 'primary' | 'success' |
| typedConfig | TuiTyped configuration object; contains tone, transparent, backgroundBlur, etc. | Object | — |
| customColor | Custom color value; supports HEX or RGB arrays | String / Array | — |
| showClose | Whether to show the close icon | Boolean | true |
| closeIcon | Class for the custom close icon | String | 'tui-icon ti-times' |
| divider | Whether to show a divider between title and content | Boolean | false |
| destroyOnClose | Whether to destroy the element when closing | Boolean | false |
| lockScroll | Whether to lock background scrolling | Boolean | true |
| closeOnBackdrop | Whether clicking the backdrop closes the dialog | Boolean | true |
| closeOnEsc | Whether pressing the Esc key closes the dialog | Boolean | true |
| zIndex | Manually control the z-index | Number | null |
| appendTo | DOM node selector to mount to | String | — |
Emits
| Event Name | Description | Callback Parameters |
|---|---|---|
| update:modelValue | Triggered when the bound value changes | value: boolean |
| open | Triggered when the Dialog opens | — |
| opened | Triggered when the Dialog opening animation ends | — |
| close | Triggered when the Dialog closes | — |
| closed | Triggered when the Dialog closing animation ends | — |
| confirm | Confirm event (usually combined with the footer slot) | — |
Slots
| Slot Name | Description |
|---|---|
| default | Main content of the Dialog |
| footer | Content of the Dialog's bottom operation area |
Hierarchy Management
In complex scenarios with multiple nested or co-existing popups, TuiDialog relies on TechUI's global service (TuiService) for intelligent stacking management:
- ESC Response (
escCounter): The component listens to the global ESC signal in real-time. WhencloseOnEscistrue, the component responds to this signal. - Intelligent Stacking Determination (Stack Management): The global service maintains a stack of currently active popups. When ESC is triggered, the component communicates with the global service to ensure only the Dialog instance at the top level (i.e., the one opened last or with the highest z-index) is closed. This mechanism perfectly solves the "accidental closing" issue in nested popup scenarios, ensuring clear and safe interaction logic.