# Migrer les fenêtres modales JavaScript d’un thème vers l’élément dialog natif

> Notre thème maison comptait six fenêtres modales construites à la main, chacune avec ses petits bugs de focus. Nous les avons migrées une par une vers l'élément HTML dialog natif.

- Auteur : Clément Hadrot
- Publié le : 2023-02-27
- Mis à jour le : 2023-02-27
- Catégorie : Accessibilité
- URL : https://wpmoderne.dev.wordpress-developpement.fr/accessibilite/migrer-modales-javascript-vers-dialog-natif/

## L’essentiel

- La bibliothèque tierce a été retirée entièrement
- Chaque migration a réduit le code JavaScript de moitié en moyenne
- Deux bugs de focus historiques ont disparu sans correctif dédié

Notre thème maison, utilisé sur une quinzaine de sites clients, s'appuyait depuis plusieurs années sur une bibliothèque JavaScript tierce pour gérer ses fenêtres modales : confirmation de suppression dans l'espace client, formulaire de connexion, visionneuse d'image, panneau de partage social, message de consentement aux cookies et fenêtre de newsletter. Cette bibliothèque, plus maintenue depuis un moment, accumulait deux bugs de focus connus que nous contournions avec des correctifs maison de plus en plus fragiles.

Après avoir étudié le support navigateur de l'élément `<dialog>` natif, désormais suffisant pour notre base de clients, nous avons décidé de migrer les six modales une par une, en commençant par la moins critique pour limiter le risque. Ce billet raconte cette migration, modale par modale.

## Première migration : la fenêtre de consentement aux cookies

Nous avons choisi de commencer par le bandeau de consentement, une modale simple sans champ de formulaire, pour valider notre méthode avant de nous attaquer aux cas plus complexes. La bibliothèque tierce nécessitait quarante-cinq lignes de configuration et d'initialisation. La version avec `<dialog>` natif tenait en douze lignes, backdrop CSS compris.

```
const cookieDialog = document.querySelector('#cookie-consent');
window.addEventListener('load', function () {
  if (!localStorage.getItem('cookies-acceptes')) {
    cookieDialog.showModal();
  }
});
cookieDialog.querySelector('button.accepter').addEventListener('click', function () {
  localStorage.setItem('cookies-acceptes', '1');
  cookieDialog.close();
});
```

## Deuxième migration : le formulaire de connexion

> L'essentiel à retenir : La bibliothèque tierce a été retirée entièrement ; Chaque migration a réduit le code JavaScript de moitié en moyenne ; Deux bugs de focus historiques ont disparu sans correctif dédié

Le formulaire de connexion était le cas le plus sensible, car il contenait un champ de saisie qui devait recevoir le focus à l'ouverture, plutôt que le focus par défaut posé sur le premier bouton. Nous avons utilisé l'attribut `autofocus` sur le champ de nom d'utilisateur, ce qui a réglé le problème sans code supplémentaire :

```
<dialog id="modale-connexion" aria-labelledby="titre-connexion">
  <h2 id="titre-connexion">Connexion</h2>
  <form method="post">
    <label for="identifiant">Identifiant</label>
    <input type="text" id="identifiant" autofocus>
    <label for="mdp">Mot de passe</label>
    <input type="password" id="mdp">
    <button type="submit">Se connecter</button>
  </form>
</dialog>
```

## Le bug historique qui a disparu tout seul

L'un des deux bugs connus de l'ancienne bibliothèque concernait précisément le formulaire de connexion : lorsqu'un utilisateur soumettait le formulaire avec une erreur de mot de passe, la modale se rechargeait dynamiquement via une requête AJAX, mais le focus retombait systématiquement sur le corps de la page plutôt que de rester dans la modale ou de revenir sur le message d'erreur. Avec `<dialog>` natif, tant que l'élément reste ouvert via `showModal()`, le piège de focus continue de s'appliquer automatiquement après chaque mise à jour du contenu interne, ce qui a fait disparaître ce bug sans correctif spécifique de notre part.

## Cas particulier : la visionneuse d'image

La visionneuse d'image posait un défi différent : elle devait s'ouvrir en plein écran avec un fond noir semi-transparent recouvrant l'intégralité de la page. La pseudo-classe `::backdrop` de l'élément `<dialog>` a permis de reproduire ce rendu directement en CSS, sans `<div>` supplémentaire pour simuler le fond :

```
#visionneuse::backdrop {
  background: rgba(0, 0, 0, 0.85);
}
```

## Bilan chiffré de la migration

| Modale | Lignes JS avant | Lignes JS après |
| --- | --- | --- |
| Consentement cookies | 45 | 12 |
| Connexion | 78 | 34 |
| Visionneuse d'image | 112 | 58 |
| Panneau de partage | 52 | 21 |
| Confirmation suppression | 38 | 15 |
| Newsletter | 61 | 29 |

> Retirer une bibliothèque tierce ne fait pas seulement gagner du poids de page : cela retire aussi, d'un coup, toutes les décisions d'implémentation douteuses accumulées au fil des versions successives de cette bibliothèque.

## En résumé

Au total, la migration des six modales a supprimé environ trois cent quarante lignes de JavaScript et permis de retirer intégralement une dépendance tierce du projet, avec un unique reste minimal de CSS pour le style du fond et les animations d'ouverture. Deux bugs de focus qui traînaient depuis longtemps ont disparu comme effet de bord de la migration, sans que nous ayons eu à les corriger explicitement. Nous recommandons cette migration à toute équipe qui maintient un thème avec plusieurs modales JavaScript maison, à condition de vérifier au préalable la compatibilité navigateur exigée par les statistiques réelles du site concerné.
