Before this lesson

Understand form buttons, DOM events and keyboard focus. Use a browser supporting native dialog.

What you will be able to do

Build a deliberate confirmation flow with dialog and distinguish modal behavior from simple visibility.

Understand the mechanism

showModal uses the top layer and makes the rest of the document inert. An open attribute or show only makes the dialog visible without equivalent modality. Native behavior reduces custom focus and layering work, but clear naming and dismissal remain necessary.

Separate dismissal from confirmation. Escape and a cancel button can dismiss; only an explicit confirmation should perform the action. Reset returnValue before opening to avoid interpreting an old confirmation after a later cancellation. This exercise changes text only.

A method=dialog form closes the dialog rather than sending a normal HTTP submission. Button values identify the outcome. Place initial focus thoughtfully and return to the trigger when closing; do not automatically focus a consequential action for long instructions.

Use ::backdrop for the overlay. Do not assume clicking it dismisses by default; test any custom light-dismiss behavior separately. A dialog is unnecessary for every notification; a status message often suffices.

Runnable example

Run HTML examples as separate .html files in a modern browser. Prepare resource files and multi-file modules as described in the lesson.

<!doctype html>
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Honeysuck practice</title></head><body>
<button id="open">Reset practice score</button><p id="status" role="status">Score: 3</p>
<dialog id="confirm" aria-labelledby="dialog-title"><h2 id="dialog-title">Reset this practice?</h2><p>This only changes the demo score.</p>
<form method="dialog"><button value="cancel" autofocus>Keep score</button><button value="confirm">Reset</button></form></dialog>
<style>dialog{max-width:min(90vw,400px);border:1px solid #b9c9be;border-radius:12px}dialog::backdrop{background:#10251c88}</style>
<script>
const trigger=document.querySelector('#open'),dialog=document.querySelector('#confirm');
trigger.addEventListener('click',()=>{dialog.returnValue='';dialog.showModal();});
dialog.addEventListener('close',()=>{if(dialog.returnValue==='confirm')document.querySelector('#status').textContent='Score: 0';trigger.focus();});
</script>
</body></html>

Trace and verify

Open and verify keyboard focus stays inside while background controls are unavailable. Keep score retains three; Reset sets zero. Reopen and Escape without another confirmation. Focus returns to the trigger after each path.

Common mistakes and boundaries

Do not replace top-layer behavior with arbitrary global z-index values. Real server actions require result and failure handling rather than displaying completion before the request succeeds.

Practice challenge

Require a reason containing at least five non-whitespace characters for confirmation while keeping cancellation available.

Reference solution and reasoning

Validate the confirmation path and give cancel formnovalidate so required fields cannot trap users. Decide whether drafts survive closing and initialize accordingly.

Further reading