Modale
In questa pagina
Un modale è un elemento popover. Qualunque pulsante il cui popovertarget combacia con l’id del modale lo apre — nessuno script da nessuna parte, sfondo, chiusura leggera, Escape e gestione del focus compresi, di cui è il browser a farsi carico.
È per questo che id è obbligatorio e che il componente solleva un errore senza — l’id è tutto il collegamento.
Modale di base
Ogni modale di questa pagina si apre davvero — provalo.
Ricostruire il sito?
fragment(
button({ popovertarget: 'demo-basic' }, 'Apri il modale'),
modal({ id: 'demo-basic', title: 'Ricostruire il sito?' },
'Esegue sitelo build e ripubblica dist/.',
),
)Con un piè di pagina
Un pulsante di chiusura è un qualunque pulsante che punta allo stesso id con popovertargetaction="hide".
Eliminare questa pagina?
fragment(
button({ color: 'danger', popovertarget: 'demo-confirm' }, 'Elimina la pagina…'),
modal({
id: 'demo-confirm',
title: 'Eliminare questa pagina?',
footer: stack({ direction: 'row', gap: 'sm' },
button({
variant: 'ghost',
color: 'neutral',
popovertarget: 'demo-confirm',
popovertargetaction: 'hide',
}, 'Annulla'),
button({ color: 'danger' }, 'Elimina'),
),
}, 'Non si può annullare. L’HTML generato viene rimosso alla prossima build.'),
)Dimensioni
Piccolo
Medio
Grande
fragment(
stack({ direction: 'row', gap: 'sm', wrap: true },
button({ variant: 'outline', color: 'neutral', popovertarget: 'demo-sm' }, 'Piccolo'),
button({ variant: 'outline', color: 'neutral', popovertarget: 'demo-md' }, 'Medio'),
button({ variant: 'outline', color: 'neutral', popovertarget: 'demo-lg' }, 'Grande'),
),
modal({ id: 'demo-sm', size: 'sm', title: 'Piccolo' }, 'size: sm — circa 24rem.'),
modal({ id: 'demo-md', title: 'Medio' }, 'Il predefinito — circa 32rem.'),
modal({ id: 'demo-lg', size: 'lg', title: 'Grande' }, 'size: lg — circa 48rem.'),
)Form dentro un modale
Nuova pagina
fragment(
button({ variant: 'soft', popovertarget: 'demo-form' }, 'Nuova pagina…'),
modal({
id: 'demo-form',
title: 'Nuova pagina',
footer: stack({ direction: 'row', gap: 'sm' },
button({ variant: 'ghost', color: 'neutral', popovertarget: 'demo-form', popovertargetaction: 'hide' }, 'Annulla'),
button({ type: 'submit' }, 'Crea'),
),
},
stack({ gap: 'md' },
textField({ label: 'Titolo', name: 'modal-title', placeholder: 'Informazioni' }),
selectField({ label: 'Estensione', name: 'modal-ext', options: ['.ht.js', '.ht.ts', '.ht.jsx'] }),
),
),
)Senza pulsante di chiusura
closable: false toglie la × nell’angolo. Escape e il clic fuori lo chiudono comunque — un popover non si può rendere davvero bloccante, e di solito è il comportamento giusto.
Premi Escape
fragment(
button({ variant: 'outline', color: 'neutral', popovertarget: 'demo-bare' }, 'Nessun pulsante di chiusura'),
modal({ id: 'demo-bare', title: 'Premi Escape', closable: false },
'Oppure clicca in un punto qualsiasi fuori da questa finestra.',
),
)Contenuto lungo
Il corpo scorre; intestazione e piè di pagina restano fermi.
Note di rilascio
Modifica 1 — qualcosa è stato corretto.
Modifica 2 — qualcosa è stato corretto.
Modifica 3 — qualcosa è stato corretto.
Modifica 4 — qualcosa è stato corretto.
Modifica 5 — qualcosa è stato corretto.
Modifica 6 — qualcosa è stato corretto.
Modifica 7 — qualcosa è stato corretto.
Modifica 8 — qualcosa è stato corretto.
Modifica 9 — qualcosa è stato corretto.
Modifica 10 — qualcosa è stato corretto.
Modifica 11 — qualcosa è stato corretto.
Modifica 12 — qualcosa è stato corretto.
fragment(
button({ variant: 'outline', color: 'neutral', popovertarget: 'demo-long' }, 'Modale lungo'),
modal({
id: 'demo-long',
title: 'Note di rilascio',
footer: button({ popovertarget: 'demo-long', popovertargetaction: 'hide' }, 'Chiudi'),
},
stack({ gap: 'md' },
...Array.from({ length: 12 }, (unused, index) =>
text({ variant: 'small', tone: 'muted' }, 'Modifica ' + (index + 1) + ' — qualcosa è stato corretto.'),
),
),
),
)Scorrimento dello sfondo
La pagina dietro un modale aperto non scorre. È l’unica cosa che l’API popover lascia a te, e qui è fatta in CSS — nessuno script, e niente da inizializzare. Passa lockScroll: false per lasciare che lo sfondo scorra come al solito.
Supporto dei browser
L’API popover è disponibile in tutti i browser attuali. In uno troppo vecchio per conoscerla, il modale viene renderizzato in linea nella pagina invece che sopra di essa — visibile e usabile, solo non sovrapposto. Non sparisce nulla.
Props
| Prop | Tipo | Predefinito | Descrizione |
|---|---|---|---|
id | string | — | Obbligatorio. Ciò a cui punta il popovertarget di un innesco. |
title | Child | — | Intestazione, e nome accessibile della finestra di dialogo. |
size | 'sm' | 'md' | 'lg' | 'md' | Larghezza massima. |
footer | Child | — | Riga in fondo, su una fascia tinta a sé. |
closable | boolean | true | Mostra la × nell’intestazione. |
closeLabel | string | 'Close' | Nome accessibile di quel pulsante. |
lockScroll | boolean | true | Impedisce alla pagina dietro di scorrere mentre è aperto. |
closeButton({ target }) renderizza quella × da sola, per un’intestazione che costruisci tu.