Summary
On the Tenants page, opening Add tenant and typing something leaves you with no way to back out. The panel has a submit button and nothing else — no ×, no Cancel, no Esc, and clicking elsewhere on the page does nothing. Add a close control.
Repro
- Go to
/ui/tenants.
- Click Add tenant.
- Type something into Tenant ID.
- Try to cancel. The only thing that works is clicking the Add tenant button again — a control labeled as the open action, so nobody looks there.
What's actually there
crates/ui/templates/pages/tenants.html:51-78 — the panel is a native <details class="addbox"> disclosure (chosen so it works without JavaScript). Its .addbox__actions block holds a single submit button. .addbox in crates/ui/assets/app.css:860-930 is position: absolute with no backdrop, so clicks outside the panel land on the page and do nothing.
<details> has no Esc behavior of its own, and no script adds one here.
The same panel pattern is used in two other places, with a different failure:
bulk-import.html:12 and bulk-import-detail.html:14 use <details class="addbox addbox--modal">. The --modal variant (app.css:931-960) stretches the <summary> across the viewport as a backdrop while open, so click-outside does close those. But there is still no × and no Esc, and an invisible backdrop is not a discoverable affordance. Whatever we do here should cover all three.
The pattern to copy
The app already solves this correctly one page over. The Resources edit modal has an explicit × — crates/ui/templates/pages/resources.html:133:
<button type="button" class="modal__x" data-modal-close aria-label="{{ i18n.t("action-cancel") }}">×</button>
— with Esc handled in crates/ui/assets/resources.js:53-54. The action-cancel Fluent key already exists (locales/en/main.ftl:66), so no new string is needed for the label.
Constraint worth knowing before starting
The whole reason these are <details> and not <dialog> is that they open without JavaScript (tenants.html:45-48 says so explicitly). A <details> cannot be closed from inside its own panel without script, so:
- Suggested: add the × as a progressive enhancement — present in the markup, hidden by default, revealed by a small pinned asset that also wires Esc and sets
details.open = false. With JS off, behavior is exactly what it is today, so nothing regresses.
- Also give the plain
.addbox a click-outside backdrop like --modal already has, so dismissal doesn't depend on JS at all.
- Alternative: move to a native
<dialog>, which gets Esc and <form method="dialog"> close buttons for free — but showModal() is JS-only, so no-JS opening would regress. Flagging the trade-off rather than picking it.
Also decide
Should the form reset when the panel closes? Today the typed values survive a close/reopen. Either behavior is defensible; pick one deliberately — "cancel" implying the input is discarded is the more common expectation.
Acceptance criteria
Pointers
crates/ui/templates/pages/tenants.html:51-78 — the reported panel
crates/ui/templates/pages/bulk-import.html:12, bulk-import-detail.html:14 — same pattern, --modal variant
crates/ui/assets/app.css:860-930 (.addbox), :931-960 (.addbox--modal backdrop trick), :927 (.addbox__actions)
crates/ui/templates/pages/resources.html:120-135 + crates/ui/assets/resources.js:53-54 — the × and Esc pattern to reuse
locales/en/main.ftl:66 — action-cancel
Summary
On the Tenants page, opening Add tenant and typing something leaves you with no way to back out. The panel has a submit button and nothing else — no ×, no Cancel, no Esc, and clicking elsewhere on the page does nothing. Add a close control.
Repro
/ui/tenants.What's actually there
crates/ui/templates/pages/tenants.html:51-78— the panel is a native<details class="addbox">disclosure (chosen so it works without JavaScript). Its.addbox__actionsblock holds a single submit button..addboxincrates/ui/assets/app.css:860-930isposition: absolutewith no backdrop, so clicks outside the panel land on the page and do nothing.<details>has no Esc behavior of its own, and no script adds one here.The same panel pattern is used in two other places, with a different failure:
bulk-import.html:12andbulk-import-detail.html:14use<details class="addbox addbox--modal">. The--modalvariant (app.css:931-960) stretches the<summary>across the viewport as a backdrop while open, so click-outside does close those. But there is still no × and no Esc, and an invisible backdrop is not a discoverable affordance. Whatever we do here should cover all three.The pattern to copy
The app already solves this correctly one page over. The Resources edit modal has an explicit × —
crates/ui/templates/pages/resources.html:133:— with Esc handled in
crates/ui/assets/resources.js:53-54. Theaction-cancelFluent key already exists (locales/en/main.ftl:66), so no new string is needed for the label.Constraint worth knowing before starting
The whole reason these are
<details>and not<dialog>is that they open without JavaScript (tenants.html:45-48says so explicitly). A<details>cannot be closed from inside its own panel without script, so:details.open = false. With JS off, behavior is exactly what it is today, so nothing regresses..addboxa click-outside backdrop like--modalalready has, so dismissal doesn't depend on JS at all.<dialog>, which gets Esc and<form method="dialog">close buttons for free — butshowModal()is JS-only, so no-JS opening would regress. Flagging the trade-off rather than picking it.Also decide
Should the form reset when the panel closes? Today the typed values survive a close/reopen. Either behavior is defensible; pick one deliberately — "cancel" implying the input is discarded is the more common expectation.
Acceptance criteria
.addboxas well as--modal.crates/ui/e2e/tests/nojs/.action-cancel) and reachable by keyboard;a11y.spec.tspasses with the panel open./ui/tenants(crates/ui/e2e/tests/tenants.spec.tshas no test for this today).Pointers
crates/ui/templates/pages/tenants.html:51-78— the reported panelcrates/ui/templates/pages/bulk-import.html:12,bulk-import-detail.html:14— same pattern,--modalvariantcrates/ui/assets/app.css:860-930(.addbox),:931-960(.addbox--modalbackdrop trick),:927(.addbox__actions)crates/ui/templates/pages/resources.html:120-135+crates/ui/assets/resources.js:53-54— the × and Esc pattern to reuselocales/en/main.ftl:66—action-cancel