Repository navigation
Description
Part of #674. ~640 lines: Dialog.tsx, useConfirm, and the four useDialog* hooks.
Carry the evidence from the spike
Branch spike/674-base-ui ported Dialog onto a headless primitive on 2026-09-13: 338 -> 240
lines, typecheck clean, all style guards green — and 82 tests red across 16 files.
Nearly all of those failures asserted the old mechanism rather than a broken guarantee:
body.style.overflow === "hidden", inert on the container, aria-modal present. A probe
confirmed the behaviour itself was intact — focus landed on the first field, the background left the
accessibility tree — the library simply reaches the same end differently.
So the risk here is not the port. It is the test rewrite. Rewriting a guard to match a new
mechanism is exactly where an earned guarantee gets silently lost.
Required of this slice
Every rewritten test names the issue whose guarantee it protects:
- Sales: both dialogs can be open at once, so the untagged dialog-error slot misattributes #480 — everything outside the topmost dialog is out of the accessibility tree.
- Dialog: two open instances brick page scrolling, and Escape closes both — plus no background inertness #482 — page scroll lock survives stacked dialogs in any close order; one Escape closes one.
- fix(web): one page, one scroll lock and one live dialog (#482) #483 — focus restoration when a stacked dialog closes, without yanking a cursor already
correctly placed in the dialog that stays open. - PWA: the update banner's announcement is swallowed while a dialog is open #485 —
anyDialogOpen/onModalStateChange, so a live region silenced under a dialog learns
the page belongs to it again. Consumed byuseMissedAnnouncement. - fix: require step-up for flock scope changes #609 —
closeDisabledsuppresses every dismissal path mid-write.
inert and scroll lock cannot be settled in jsdom and need Playwright, per #501.
Activity
feat(web): convert the Dashboard and app shell to MUI (#829) (#883)
mforce commentedon Sep 16, 2026
Note from #829 (2026-09-16): the phone More menu is still rendered through the current
Dialogcomponent. #883 converted the tab bar toBottomNavigationbut left More on the existing dialog because this slice had not landed, so the design doc's D2 pair 13 question (More asSwipeableDrawer anchor="bottom"versus keeping it on MUIDialogafter #827; §7 owner-review row) is still open and lands here or in a follow-up onceDialogis MUI.BottomNav.tsx's fifth slot carriesaria-haspopup="dialog",aria-expandedandaria-current; whichever component More becomes must keep those three, andanyDialogOpen()must be re-checked for #485 if More leavesDialog.feat(web): replace NamedEntityPicker's combobox with MUI Autocomplete (…