Skip to content

Dialog ​

Modal dialog component with customizable title, content, actions, and layout options. Built on Vuetify's Dialog component with support for persistent, fullscreen, and scrollable modes.

Overview ​

VOvDialog provides a flexible modal dialog wrapper for displaying content, forms, and user prompts. It supports customizable headers with titles, subtitles, and icons; formatted content with styling; flexible action buttons; and optional persistent, fullscreen, and scrollable layouts. The component handles click actions, form submissions, and cancellations with clear event emissions.

Features:

  • Customizable title, subtitle, and icon
  • Formatted content with styling support
  • Flexible action buttons with custom formatting
  • Built-in submit, cancel, and custom actions
  • Persistent, fullscreen, and scrollable modes
  • Responsive width based on screen breakpoints
  • Slot support for complex content and forms
  • v-model binding for dialog visibility
  • Full TypeScript support

Usage ​

Examples
vue
<template>
  <v-container fluid>
    <v-row>
      <v-col cols="12">
        <v-btn>
          Simple Dialog
          <v-ov-dialog
            activator="parent"
            title="Simple Dialog"
            content="Content for Simple Dialog"
            actions="close"
            actionCancel="close"
            @action="console.log('closed')"
          />
        </v-btn>
      </v-col>
      <v-col cols="12">
        <v-btn>
          Formatted Dialog
          <v-ov-dialog
            activator="parent"
            title="Formatted Dialog"
            subtitle="With Subtitle and Icon"
            icon="$mdiAccount"
            color="#E3F2FD"
            content="Content for Formatted Dialog"
            :contentFormat="{ color: 'blue' }"
            :actions="[
              { name: 'agree', format: { text: 'agree', color: 'green' } },
              { name: 'disagree', format: { text: 'disagree', color: 'red' } },
              { name: 'not sure', format: { text: 'not sure', color: 'orange' } },
            ]"
            :actionFormat="{ variant: 'outlined' }"
            actionSubmit="agree"
            actionCancel="disagree"
            @action="(action: OvAction) => console.log('action', action)"
            @submit="(action: OvAction) => console.log('submitted', action)"
            @cancel="() => console.log('cancelled')"
          />
        </v-btn>
      </v-col>
      <v-col cols="12">
        <v-btn>
          Dialog with Form
          <v-ov-dialog persistent activator="parent" title="Dialog with Form">
            <template v-slot:content="{ onClose }">
              <v-ov-form
                :options="formOptions"
                @submit="
                  (data: OvFormData) => {
                    submitForm(data)
                    onClose()
                  }
                "
                @cancel="onClose()"
              />
            </template>
          </v-ov-dialog>
        </v-btn>
      </v-col>
      <v-col cols="12">
        <v-btn>
          Fullscreen Dialog
          <v-ov-dialog
            activator="parent"
            title="Fullscreen Dialog"
            content="Content for Fullscreen Dialog"
            actions="close"
            actionCancel="close"
            @action="console.log('closed')"
            fullscreen
          />
        </v-btn>
      </v-col>
      <v-col cols="12">
        <v-btn>
          Scrollable Dialog
          <v-ov-dialog
            activator="parent"
            title="Scrollable Dialog"
            :content="'Content for Scrollable Dialog. '.repeat(250)"
            actions="close"
            actionCancel="close"
            @action="console.log('closed')"
            scrollable
          />
        </v-btn>
      </v-col>
    </v-row>
  </v-container>
</template>

<script setup lang="ts">
definePage({
  meta: {
    visibility: 'with-role',
    access: 'with-role',
    roles: ['developer'],
  },
})
import { type OvFormOptions, type OvFormData } from '@/components/'
import { ref } from 'vue'

const formOptions = ref<OvFormOptions>({
  cols: 2,
  fields: [
    { name: 'id', label: 'Key', type: 'text', readonly: true, value: '12345' },
    {
      name: 'content',
      label: 'Value',
      type: 'text',
      rules: [{ type: 'required', params: true, message: 'Value is required' }],
    },
  ],
  actions: ['cancel', 'submit'],
  actionSubmit: 'submit',
  actionCancel: 'cancel',
})

function submitForm(formData: OvFormData) {
  console.log('form submitted', formData)
}
</script>

API ​

Props ​

PropTypeDefaultDescription
persistentbooleanfalsePrevent dialog from closing when clicking outside
fullscreenbooleanfalseDisplay dialog in fullscreen mode
scrollablebooleanfalseEnable scrolling for long content
closeablebooleanfalseAdds close button that closes the dialog
copyablebooleanfalseAdds copy to clipboard button
titlestring-Dialog title text
subtitlestring-Dialog subtitle text (displayed below title)
iconstring-Icon to display in dialog header
colorstring-Background color for dialog card
contentstring-Dialog content text
contentFormatOvFormat | OvFormat[]-Formatting options for content
actionsOvAction | OvAction[]-Action buttons to display at bottom
actionFormatOvFormat | OvFormat[]-Default formatting for all action buttons
actionSubmitstring | string[]-Action name(s) that trigger submit event
actionCancelstring | string[]-Action name(s) that trigger cancel event and close dialog

Events ​

EventPayloadDescription
actionaction: OvActionEmitted when any action button is clicked (except submit/cancel)
submitaction: OvActionEmitted when an action marked as submit is clicked
cancel-Emitted when an action marked as cancel is clicked or before closing

Exposed Properties ​

PropertyTypeDescription
dialogRef<boolean>Boolean ref for dialog visibility - can be used to open/close programmatically

Content Formatting ​

The contentFormat prop supports conditional formatting with validation rules:

typescript
interface OvFormat {
  text?: string              // Override content text
  icon?: string              // Add icon to content
  color?: string             // Color styling
  variant?: string           // Button variant
  density?: string           // Content density
  size?: string              // Size adjustment
  rounded?: boolean          // Border radius
  class?: string             // Custom CSS class
  rules?: OvRule[]           // Conditional rules
}

When contentFormat includes formatting properties, the content is displayed as a chip instead of plain text.

Action Format ​

Actions can be defined as:

String (simple):

typescript
actions: ['close', 'cancel', 'submit']

Object (with formatting):

typescript
actions: [
  { name: 'agree', format: { text: 'Agree', color: 'green' } },
  { name: 'disagree', format: { text: 'Disagree', color: 'red' } },
  { name: 'notify', format: { text: 'Notify Me', icon: '$mdiBell' } }
]

Action Handler Logic ​

The component automatically routes actions based on the actionSubmit and actionCancel props:

  1. If action name matches actionCancel, emits cancel event and closes dialog
  2. If action name matches actionSubmit, emits submit event and closes dialog
  3. Otherwise, emits action event and keeps dialog open

Slots ​

content ​

Slot for custom content instead of simple text:

vue
<v-ov-dialog title="Dialog with Slot Content">
  <template v-slot:content="{ onClose }">
    <!-- Custom content here -->
    <v-btn @click="onClose">Close</v-btn>
  </template>
</v-ov-dialog>

Slot scope provides:

  • onClose() - Function to close the dialog

actions ​

Slot for custom action buttons:

vue
<v-ov-dialog title="Dialog with Custom Actions">
  <template v-slot:actions>
    <v-btn color="primary">Custom Action</v-btn>
  </template>
</v-ov-dialog>

Notes ​

  • Dialog width respects the Vuetify breakpoint system and automatically adjusts to screen size
  • Content displays as a chip (with styling) if contentFormat is provided; otherwise as plain text
  • Multiple action names can be marked as submit/cancel by passing arrays: actionSubmit="['agree', 'yes']"
  • The persistent prop requires users to use an action button to close the dialog
  • Slot content has access to an onClose function for programmatic closure
  • Icon supports Material Design Icon syntax (e.g., $mdiAccount, $mdiAlert)
  • Dialog respects all Vuetify color system colors and theme customizations