Skip to content

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.

vue
<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% or 300 pixel 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.
vue
<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, and fixed.
  • dragContainment: Restricts the dragging range to within the visible area.
  • resetDragOnClose: Whether to reset the position after closing.
vue
<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.

vue
<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).

vue
<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.

vue
<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

PropertyDescriptionTypeDefault
modelValue(v-model) Whether to show the DialogBooleanfalse
titleTitle textString
widthPopup width; supports 300 (px) or '40%'String / Numbernull
topOffset from the topString / Number
alignCenterWhether to center verticallyBooleanfalse
centerWhether to center the Header and Content inside the popupBooleanfalse
fullscreenWhether to display in full screenBooleanfalse
modalWhether a mask layer is requiredBooleantrue
draggableWhether to enable header draggingBooleanfalse
positionTypeDrag positioning type; options: `'transform''absolute''fixed'`
dragContainmentWhether to restrict dragging to the window rangeBooleantrue
resetDragOnCloseWhether to reset the drag position when closingBooleantrue
typeSemantic type; options: `'default''primary''success'
typedConfigTuiTyped configuration object; contains tone, transparent, backgroundBlur, etc.Object
customColorCustom color value; supports HEX or RGB arraysString / Array
showCloseWhether to show the close iconBooleantrue
closeIconClass for the custom close iconString'tui-icon ti-times'
dividerWhether to show a divider between title and contentBooleanfalse
destroyOnCloseWhether to destroy the element when closingBooleanfalse
lockScrollWhether to lock background scrollingBooleantrue
closeOnBackdropWhether clicking the backdrop closes the dialogBooleantrue
closeOnEscWhether pressing the Esc key closes the dialogBooleantrue
zIndexManually control the z-indexNumbernull
appendToDOM node selector to mount toString

Emits

Event NameDescriptionCallback Parameters
update:modelValueTriggered when the bound value changesvalue: boolean
openTriggered when the Dialog opens
openedTriggered when the Dialog opening animation ends
closeTriggered when the Dialog closes
closedTriggered when the Dialog closing animation ends
confirmConfirm event (usually combined with the footer slot)

Slots

Slot NameDescription
defaultMain content of the Dialog
footerContent 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. When closeOnEsc is true, 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.

Released under the MIT License.