Overlays

Dialog

Finestra modale overlay con supporto a posizionamento configurabile, trascinamento, massimizzazione e slot header/footer. `Modal` è un alias deprecato che punta a questo componente.

Import

import { Dialog } from '@pzeta/vue-components'
// oppure con plugin selettivo:
import { OverlaysPlugin } from '@pzeta/vue-components'
app.use(OverlaysPlugin)

Esempio Base

Props

PropTipoDefaultDescrizione
modelValuebooleanfalseVisibilità del dialog (v-model)
visiblebooleanfalseAlias per modelValue (v-model:visible, compatibilità PrimeVue)
headerstring | nullnullTesto del titolo nell'header
iconstring | nullnullClasse CSS dell'icona nell'header (es. pi pi-info)
modalbooleantrueMostra overlay scuro dietro il dialog
positionDialogPosition'center'Posizione del dialog sullo schermo
sizeDialogSize'medium'Dimensione predefinita del dialog
closablebooleantrueMostra il pulsante di chiusura
closeIconstringClasse CSS icona di chiusura (default dal ConfigPlugin)
dismissableMaskbooleanfalseChiude al click sull'overlay. Dalla 1.9.0 il default è false
closeOnEscapebooleantrueChiude alla pressione di Escape
blockScrollbooleantrueBlocca lo scroll del body quando aperto
showHeaderbooleantrueMostra la sezione header
draggablebooleantruePermette di trascinare il dialog dall'header. Dalla 1.9.0 il default è true
maximizablebooleanfalseMostra pulsante per massimizzare a schermo intero
keepInViewportbooleantrueImpedisce al dialog di uscire dai bordi del viewport durante il drag
responsivebooleantrueAbilita comportamento responsive su schermi piccoli
breakpointsRecord<string, string> | nullnullBreakpoints responsive per larghezza dinamica (es. { '960px': '75vw' })
stylestring | Record<string, string | number> | nullnullStile inline per il container del dialog
contentStylestring | Record<string, string | number> | nullnullStile inline per l'area contenuto
contentClassstring | nullnullClasse CSS aggiuntiva per l'area contenuto

DialogPosition

type DialogPosition =
  | 'center'      // Centro schermo (default)
  | 'top'         // Centro in alto
  | 'bottom'      // Centro in basso
  | 'left'        // Centro a sinistra
  | 'right'       // Centro a destra
  | 'topleft'     // Angolo superiore sinistro
  | 'topright'    // Angolo superiore destro
  | 'bottomleft'  // Angolo inferiore sinistro
  | 'bottomright' // Angolo inferiore destro

DialogSize

type DialogSize = 'small' | 'medium' | 'large' | 'xlarge'
// small: ~300px | medium: ~500px (default) | large: ~800px | xlarge: ~1140px

Emits

EventoPayloadDescrizione
update:modelValuebooleanAggiornamento visibilità per v-model
update:visiblebooleanAggiornamento visibilità per v-model:visible
showDialog reso visibile
hideDialog nascosto
closeEventDialog chiuso tramite pulsante o ESC
maximizeEventDialog massimizzato
unmaximizeEventDialog ripristinato dalla modalità massimizzata
maskClickEventClick sull'overlay esterno. Emesso a ogni click sulla mask, anche quando non chiude il dialog

Slot

SlotScopeDescrizione
defaultContenuto principale del dialog
header{ close: () => void }Sostituzione completa dell'header
footerArea footer (tipicamente pulsanti azione)
closeiconIcona personalizzata per il pulsante di chiusura
maximizeicon{ maximized: boolean }Icona personalizzata per il pulsante maximize/restore

Chiusura e trascinamento

Dalla versione 1.9.0 il Dialog si comporta come una finestra: non si chiude al click fuori e si trascina dall'header. I due default proteggono lo stesso caso d'uso — un dialogo che ospita un form — dove un click accidentale scartava quanto digitato e la finestra copriva i dati necessari a compilarla.

GestoComportamento
Click sulla maskIl dialog resta aperto e pulsa brevemente; maskClick viene emesso
EscapeChiude (disattivabile con :close-on-escape="false")
Pulsante XChiude (rimuovibile con :closable="false")
Trascinamento dall'headerSposta il dialog, entro i bordi del viewport

Riattivare la chiusura dal backdrop

Per un dialogo di sola lettura, senza campi da compilare:

Reagire al click sulla mask senza chiudere

maskClick è emesso a ogni click sull'overlay, dismissibile o meno: utile per avvisare che ci sono modifiche non salvate.

Dialog fisso al centro

:draggable="false" disattiva il trascinamento e riporta l'header a testo selezionabile.

Pulsazione di attenzione

Quando la mask non chiude, il pannello esegue una breve pulsazione (classe hs-overlay-attention) invece di non reagire affatto: senza riscontro visivo l'interfaccia sembra bloccata. L'animazione agisce sulla proprietà CSS scale — indipendente dal transform usato dal trascinamento, che quindi non salta — ed è disattivata sotto prefers-reduced-motion: reduce.

Migrazione da versioni precedenti alla 1.9.0

<!-- Prima della 1.9.0: chiudeva dal backdrop, non si trascinava -->
<Dialog v-model:visible="visible" header="Titolo" />

<!-- Stesso comportamento sulla 1.9.0 -->
<Dialog v-model:visible="visible" header="Titolo" dismissable-mask :draggable="false" />

Esempi

Dialog con posizione e dimensione

Dialog maximizable e draggable

Dialog senza header (solo close floating)

Compatibilità v-model:visible (pattern PrimeVue)

<Dialog v-model:visible="isOpen" header="Titolo">
  <p>Contenuto</p>
</Dialog>

Alias deprecati

Il componente Modal è un alias backward-compatible che punta a Dialog. I tipi correlati sono anch'essi alias deprecati.

// Deprecato — usare Dialog
import { Modal } from '@pzeta/vue-components'
// Preferire:
import { Dialog } from '@pzeta/vue-components'
// Tipi deprecati
import type { ModalProps, ModalEmits, ModalPosition, ModalSize } from '@pzeta/vue-components'
// Preferire:
import type { DialogProps, DialogEmits, DialogPosition, DialogSize } from '@pzeta/vue-components'

Accessibilità

  • Renderizzato con role="dialog" e aria-modal="true"
  • aria-labelledby collegato automaticamente all'ID del titolo nell'header
  • aria-describedby collegato automaticamente all'ID dell'area contenuto
  • Chiusura tramite tasto Escape (disabilitabile con :close-on-escape="false")
  • Blocco scroll del body quando aperto (disabilitabile con :block-scroll="false")
  • Il componente usa <Teleport to="body"> per garantire corretto z-index e stacking context

TypeScript

import type { DialogProps, DialogEmits, DialogPosition, DialogSize } from '@pzeta/vue-components'