Dialog

Composant modal natif basé sur l'élément HTML <dialog>. S'ouvre via un bouton déclencheur, se ferme via un bouton de fermeture ou programmatiquement. Supporte l'enchaînement de modals, les variantes colorées et trois modificateurs de taille. L'animation d'ouverture et de fermeture repose sur des transitions CSS.

Stable JS requis Accessible

Aperçu


LIVE PREVIEW — DIALOG PAR DÉFAUT

Titre du dialog

Ceci est un exemple de dialog simple. Vous pouvez y inclure n'importe quel contenu.

Premier dialog

Ce dialog va en ouvrir un second à la fermeture.

Second dialog

Vous avez atteint le dernier dialog de la chaîne.

Structure HTML


CODE HTML

Dialog title

Dialog content.

💡 Indispensable

Chaque data-target doit correspondre exactement à l'id du dialog associé. Utilisez le format #id — le JS utilise document.querySelector() pour les boutons déclencheurs.


⚠️ L'élément cible doit obligatoirement être un <dialog> natif. Le JS vérifie instanceof HTMLDialogElement avant d'ouvrir.

👉 Pour l'accessibilité

Les attributs suivants sont ajoutés automatiquement par Dialog.init() :

Les attributs suivants doivent être posés manuellement dans le HTML :

Classes CSS


CLASSE ÉLÉMENT DESCRIPTION
.dialog <dialog> Classe de base. Positionne le dialog en centré fixe, applique bordure, border-radius, fond et transitions CSS d'ouverture/fermeture.
.dialog-sm <dialog> Largeur et hauteur max réduites via --dialog-width-sm et --dialog-max-height-sm.
.dialog-md <dialog> Largeur et hauteur max intermédiaires.
.dialog-lg <dialog> Largeur et hauteur max augmentées.
.dialog-header <header> En-tête du dialog avec padding via variables CSS.
.dialog-body <div> Corps du dialog avec flex: 1 1 auto et overflow-y: auto pour les contenus longs.
.dialog-footer <footer> Pied du dialog avec padding via variables CSS. Optionnel.
.dialog-{color} <dialog> Variante colorée générée pour chaque couleur de la map $colors. Applique background-color, border-color et color via --content-on-{color}.
.show <dialog> Ajoutée par le JS à l'ouverture. Déclenche la transition CSS vers l'état visible (opacity: 1, scale(1)). Active également le fond du ::backdrop.

Variantes


Dialog simple

Un bouton ouvre un dialog. Le bouton de fermeture à l'intérieur le referme.

DIALOG SIMPLE HTML

Title

Content.

Dialog enchaîné

Un bouton à l'intérieur d'un dialog peut porter simultanément data-dismiss="dialog" et data-ui="dialog" avec un data-target pointant vers un autre dialog. Le JS ferme le dialog courant puis ouvre le suivant, en respectant la transition CSS.

DIALOG ENCHAÎNÉ HTML

First dialog

Content.

Second dialog

Content.

Variantes de couleur

Les variantes sont générées automatiquement pour chaque entrée de la map $colors. La classe suit le pattern .dialog-{name}.

COULEURS DISPONIBLES HTML

Tailles


Les modificateurs de taille s'appliquent directement sur l'élément <dialog> et surchargent --dialog-width et
--dialog-max-height.

LIVE PREVIEW — TAILLES

.dialog-sm

Taille sm.

.dialog-md

Taille md.

.dialog-lg

Taille lg.

États


ÉTAT ÉLÉMENT DESCRIPTION
Fermé :not([open]) État initial. Le dialog n'est pas dans le DOM visuel. Aucune classe n'est présente.
En ouverture [open] Le JS appelle dialog.showModal(). Le dialog est rendu avec opacity: 0 et scale(0). La classe .show est ajoutée immédiatement après pour déclencher la transition.
Ouvert [open].show Transition terminée. Le dialog est pleinement visible (opacity: 1, scale(1)). Le backdrop est actif.
En fermeture [open]:not(.show) La classe .show est retirée. La transition CSS ramène le dialog à opacity: 0 et scale(0). dialog.close() est appelé à la fin de la transition.
En animation [data-animating="true"] Attribut posé pendant toute la durée d'une transition. Bloque les ouvertures ou fermetures parasites.

JavaScript


Le composant est piloté par la classe Dialog. Elle s'appuie sur la délégation d'événements (un seul listener sur document), les transitions CSS pour les animations, et l'API native HTMLDialogElement.

INITIALISATION

SCRIPT D'INITIALISATION JS
import Dialog from './Dialog.js';

// A single instance is enough for the entire page.
new Dialog();

ℹ️ Singleton

La classe implémente un guard Dialog.initialized : instancier Dialog plusieurs fois n'entraîne aucun doublon de listeners.

ATTRIBUTS DE DONNÉES REQUIS

ATTRIBUT ÉLÉMENT DESCRIPTION
data-ui="dialog" <button> Identifie le bouton comme déclencheur d'ouverture. Peut aussi être combiné avec data-dismiss="dialog" pour enchaîner deux dialogs.
data-target <button> Sélecteur du dialog cible. Doit être au format #id. Requis sur tout bouton portant data-ui="dialog".
data-dismiss="dialog" <button> Identifie le bouton de fermeture. Le JS remonte au <dialog> parent le plus proche et appelle Dialog.hide().

MÉTHODES STATIQUES

MÉTHODE DESCRIPTION
Dialog.init() Parcourt tous les boutons [data-ui="dialog"] et ajoute aria-modal="true" sur leur dialog cible si absent.
Dialog.open(dialog) Appelle dialog.showModal(), ajoute .show et gère la fin de transition via transitionend. Émet dialog:beforeOpen et dialog:afterOpen.
Dialog.hide(dialog) Retire .show, attend la fin de la transition puis appelle dialog.close(). Émet dialog:beforeClose et dialog:afterClose.
Dialog.handleOpen(button) Résout le dialog cible via data-target. Gère le cas d'enchaînement : si le bouton porte aussi data-dismiss, ferme le dialog courant avant d'ouvrir le suivant.
Dialog.emitEvent(target, name, dialog) Émet un CustomEvent avec bubbles: true et detail: { element: dialog }. Utilisé pour les quatre événements du cycle de vie.

ÉVÉNEMENTS

ÉVÉNEMENT DÉCLENCHEMENT
dialog:beforeOpen Émis sur le dialog juste avant l'appel à showModal().
dialog:afterOpen Émis sur le dialog à la fin de la transition d'ouverture.
dialog:beforeClose Émis sur le dialog juste avant le retrait de .show.
dialog:afterClose Émis sur le dialog à la fin de la transition de fermeture, après dialog.close().

UTILISATION MANUELLE

UTILISATION MANUELLE (OPTIONNELLE) JS
// Open a dialog programmatically
const dialog = document.getElementById('my-dialog');
Dialog.open(dialog);

// Close a dialog programmatically
Dialog.hide(dialog);

// Listen to lifecycle events
dialog.addEventListener('dialog:afterOpen', (e) => {
  console.log('Dialog opened', e.detail.element);
});

CSS Custom Properties


TOKEN RÔLE
--dialog-width Largeur par défaut du dialog
--dialog-max-height Hauteur maximale par défaut
--dialog-width-sm Largeur — taille sm
--dialog-max-height-sm Hauteur maximale — taille sm
--dialog-width-md Largeur — taille md
--dialog-max-height-md Hauteur maximale — taille md
--dialog-width-lg Largeur — taille lg
--dialog-max-height-lg Hauteur maximale — taille lg
--dialog-border-width Épaisseur de la bordure
--dialog-border-style Style de bordure (solid, dashed…)
--dialog-border-radius Rayon des coins
--dialog-border-color Couleur de la bordure
--dialog-background-color Couleur de fond du dialog
--dialog-backdrop-background Couleur du backdrop affiché derrière le dialog (défini par thème)
--dialog-header-padding-x Padding horizontal de l'en-tête
--dialog-header-padding-y Padding vertical de l'en-tête
--dialog-body-padding-x Padding horizontal du corps
--dialog-body-padding-y Padding vertical du corps
--dialog-footer-padding-x Padding horizontal du pied
--dialog-footer-padding-y Padding vertical du pied
--content-on-{color} Couleur du texte sur fond coloré. Garantit le contraste sur chaque variante de la map.
EXEMPLE DE PERSONNALISATION CSS
/* Global variables */
:root {
  --dialog-border-radius: 8px;
  --dialog-width: 40rem;
  --dialog-max-height: 80vh;
}

/* Light theme */
:root[data-theme="light"] {
  color-scheme: light;
  --dialog-backdrop-background: rgba(0, 0, 0, 0.5);
}

/* Dark theme */
:root[data-theme="dark"] {
  color-scheme: dark;
  --dialog-backdrop-background: rgba(225, 225, 225, 0.5);
}

Accessibilité


PRATIQUE DÉTAIL
aria-modal="true" Ajouté automatiquement par Dialog.init(). Indique aux technologies d'assistance que le contenu derrière le dialog est inerte.
aria-labelledby À poser manuellement sur le <dialog>. Doit pointer vers l'id du titre dans .dialog-header. Permet aux lecteurs d'écran d'annoncer le libellé du dialog.
aria-label="Close dialog" À poser manuellement sur le bouton de fermeture. Fournit un libellé explicite aux technologies d'assistance.
aria-hidden="true" À poser manuellement sur .close-indicator. Masque l'icône décorative aux lecteurs d'écran.
Élément <dialog> Utilisez toujours l'élément HTML natif <dialog>. Il gère nativement le piège du focus, la touche Échap et l'inertie du contenu derrière le modal.
Élément <button> Utilisez toujours un <button> pour les déclencheurs et les boutons de fermeture afin d'assurer la navigation clavier native.

⚠️ Attention

Ne pas fermer le dialog via dialog.close() directement sans passer par Dialog.hide() : la transition CSS de fermeture serait ignorée et l'événement dialog:afterClose ne serait pas émis.

Notes & bonnes pratiques


✅ À faire

Toujours fournir un id unique à chaque dialog et le référencer dans aria-labelledby (titre) et data-target (bouton déclencheur).

✅ À faire

Pour écouter les événements du cycle de vie, branchez-vous sur le dialog lui-même — les événements remontent (bubbles: true) et peuvent aussi être écoutés sur document.

❌ À éviter

Ne pas instancier Dialog avant le chargement du DOM. Utilisez DOMContentLoaded ou placez le script en bas de page.

❌ À éviter

Ne pas utiliser dialog.showModal() directement — le JS gère la séquence complète (animation, événements, guard data-animating). Passez toujours par Dialog.open().

ℹ️ Compatibilité

L'élément <dialog> est supporté nativement par tous les navigateurs modernes. Pour IE11 ou les navigateurs anciens, un polyfill comme dialog-polyfill est nécessaire.


Dialog · WEBDEV-UI DOCS / V1