Accessible Modal Dialog with the dialog Element

Build a native HTML modal with showModal, labelled and described content, Escape and backdrop dismissal, and a live result message.

HtmlForm Validation

Code

snippet
<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Accessible confirmation dialog</title>
  <style>
    :root {
      color-scheme: light dark;
      font-family: system-ui, sans-serif;
    }

    body {
      margin: 0;
      padding: 2rem;
    }

    button {
      font: inherit;
      padding: 0.6rem 1rem;
      border: 1px solid currentColor;
      border-radius: 0.4rem;
      background: canvas;
      color: canvastext;
      cursor: pointer;
    }

    button:focus-visible {
      outline: 3px solid #4f46e5;
      outline-offset: 2px;
    }

    dialog {
      max-width: 32rem;
      border: 1px solid gray;
      border-radius: 0.75rem;
      padding: 1.5rem;
    }

    dialog::backdrop {
      background: rgb(0 0 0 / 55%);
    }

    .actions {
      display: flex;
      gap: 0.75rem;
      justify-content: flex-end;
      margin-top: 1.5rem;
    }
  </style>
</head>
<body>
  <main>
    <h1>Delete project</h1>
    <p>Deleting a project removes its deployments and environment variables.</p>
    <button type="button" id="open-dialog">Delete project…</button>
    <p id="status" role="status" aria-live="polite"></p>
  </main>

  <dialog id="confirm-dialog" aria-labelledby="dialog-title" aria-describedby="dialog-desc">
    <form method="dialog">
      <h2 id="dialog-title">Delete “Atlas”?</h2>
      <p id="dialog-desc">
        This permanently removes the project and its 12 deployments. This action cannot be undone.
      </p>
      <div class="actions">
        <button value="cancel" autofocus>Cancel</button>
        <button value="confirm">Delete permanently</button>
      </div>
    </form>
  </dialog>

  <script>
    const dialog = document.querySelector('#confirm-dialog');
    const openButton = document.querySelector('#open-dialog');
    const status = document.querySelector('#status');

    openButton.addEventListener('click', () => {
      dialog.returnValue = '';
      dialog.showModal();
    });

    dialog.addEventListener('close', () => {
      status.textContent = dialog.returnValue === 'confirm'
        ? 'Project deleted.'
        : 'Deletion cancelled.';
      openButton.focus();
    });

    dialog.addEventListener('click', (event) => {
      if (event.target === dialog) {
        dialog.close('cancel');
      }
    });
  </script>
</body>
</html>