Representative interview topic

Frontend interview: How should dialog closedby control dismissal?

FrontendHard
Offer.cc Editorial TeamPublished Updated

Question

Design an HTML dialog for a destructive confirmation with a validated form. Compare closedby=none, closerequest, and any; explain showModal versus show, Popover API, focus, close reasons, and fallback.

Prompt and context

An admin console needs a destructive confirmation and a reason form. Some flows must close only through an explicit action; others may close with Escape or an outside click. Design the native dialog element dismissal policy for keyboard, touch, and validation paths.

MDN defines closedby values none, closerequest, and any: developer mechanisms only, platform close requests plus developer mechanisms, or all three mechanisms. Modal dialogs use showModal(); non-modal dialogs use show().

What the interviewer is testing

The candidate should map business risk to dismissal policy, distinguish modal dialogs from popovers, and explain Escape, light dismiss, close(), requestClose(), method="dialog", initial focus, restoration, and form validation.

Clarifying questions to ask first

  • May a destructive confirmation be dismissed accidentally, and must unsaved input remain?
  • Is Escape or an outside click equivalent to cancel, or does it require another confirmation?
  • Should a cancel button bypass required-field validation?
  • Must unsupported browsers provide identical dismissal behavior?
  • Where should focus return when the dialog closes?

30-second answer framework

“For destructive actions I use showModal() with closedby="closerequest", or none for the strictest confirmation, plus explicit cancel and confirm buttons. A low-risk information panel can use any or popover="auto". A form with method="dialog" returns a value; a cancel button can use formnovalidate when it must bypass validation. I set an intentional initial focus and restore focus to the trigger. Capability detection provides an explicit-button and manual-keyboard fallback.”

Step-by-step deep dive

Step 1: Choose modal or non-modal

showModal() makes the rest of the document inert and fits destructive confirmation or required work. show() leaves the page interactive for an auxiliary panel. Toggling only the open attribute does not establish modal focus and background semantics.

Step 2: Map risk to closedby

closedby="none" permits only developer-defined closing and suits irreversible confirmation. closerequest also accepts Escape or a platform close request. any adds outside-click light dismiss and suits low-risk information.

html
<dialog id="delete-dialog" closedby="closerequest">
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="confirm">Delete</button>
  </form>
</dialog>

Step 3: Handle Escape, request-close, and close

Escape or a platform gesture is a close request. requestClose() can run the request-close path so the application can confirm or intercept it. close() closes directly and may set returnValue. Never interpret Escape as confirmed deletion.

Step 4: Manage and restore focus

When a modal opens, focus the best input, cancel button, or heading; do not put tabindex on the dialog element. On close, return focus to the trigger, or to a stable replacement if the trigger was removed.

Step 5: Use form method=dialog deliberately

method="dialog" closes the dialog and preserves form control state without sending a network request; the button value becomes returnValue. If cancel must bypass required validation, use formnovalidate or explicit close() so the user is never trapped.

Step 6: Distinguish dialog from Popover

A popover is non-modal and lives in the top layer. popover="auto" supports light dismiss; manual stays open until explicitly hidden and allows multiple independent popovers. Do not use a popover where modal inertness is required.

Step 7: Detect support and provide fallback

Check HTMLDialogElement, showModal, and closedby support. Without them, provide explicit controls, manual Escape handling, focus management, and background blocking. The fallback must preserve the same cancel and confirm contract.

Step 8: Test dismissal and accessibility

Test Tab, Escape, outside click, touch, failed validation, repeated opens, multiple modals, back gestures, and older browsers. Record close reason (confirm, cancel, escape, light-dismiss) and use a screen reader to verify naming, state, and focus movement.

Model high-quality answer

“A destructive confirmation uses showModal() and closedby="closerequest"; the strictest flow uses none with an explicit cancel button. Low-risk information may use any or popover="auto". method="dialog" returns the result, and cancel can bypass validation when appropriate. I set initial focus, restore trigger focus, detect support, and fall back to explicit controls and manual keyboard/focus handling. Tests cover every dismissal source and assistive technology.”

Common mistakes

  • Using any for every dialog → destructive actions close accidentally → map closedby to risk.
  • Adding tabindex to dialog → focus semantics are wrong → focus an inner control or heading.
  • Treating close as requestClose → confirmation logic is skipped → distinguish requested and direct close.
  • Making a required form’s cancel button fail validation → the user is trapped → use formnovalidate or close.
  • Replacing a modal with a popover → the background stays interactive → use showModal when inertness matters.
  • Testing only a mouse → keyboard and touch users cannot leave → cover Escape, Tab, outside click, and screen readers.

Follow-up questions and strong responses

Follow-up 1: What is the core difference between closerequest and none?

closerequest accepts Escape or a platform close request in addition to developer controls; none accepts only developer controls and fits irreversible actions.

Follow-up 2: Why is showModal more reliable than open?

It establishes modal state, background inertness, and browser focus behavior. Setting open alone creates a non-modal dialog.

Follow-up 3: What is returnValue after Escape?

Escape does not represent a submit button value unless the application sets one. Record the close reason separately as escape or request-close.

Follow-up 4: How can cancel bypass required validation?

Put formnovalidate on the cancel control or call close("cancel"); keep normal validation on confirm.

Follow-up 5: What is the fallback for older browsers?

Provide explicit open/close controls and manually manage Escape, focus trapping, background blocking, and close reasons. Keep contract tests the same when native support is restored.

Public sources

Related questions