refactor(ui): extract shared modal-dialog controller for Dialog + Sheet - #35
refactor(ui): extract shared modal-dialog controller for Dialog + Sheet#35nsollazzo wants to merge 2 commits into
Conversation
Dialog and Sheet carried byte-identical native-`<dialog>` wiring: the showModal()/close() effect, the teardown focus-restore effect, and the single-dismissal handleClose() (save/restore previouslyFocused, sync the `open` binding, notify onclose). Two copies of subtle, a11y-critical focus logic risk silent divergence on any future fix. Consolidated into useModalDialog() in src/lib/actions/modalDialog.svelte.ts, following the repo's getter-param convention (cf. useOverlayTheme(invert)). Logic moved verbatim — behavior is unchanged. Internal helper (not exported from index.ts). Net -37 lines in the components (-53/+16). Gates green: svelte-check (0), prettier+eslint, knip, 300/300 unit tests (incl. the backdrop double-fire regression guards), build + svelte-package + are-the-types-wrong. Co-Authored-By: Paperclip <noreply@paperclip.ing>
Review verdict: ✅ APPROVE — clean, faithful extraction; all four gates green
Reviewed the whole diff plus the code it touches (both components, the extracted controller, Verbatim claim — verifiedDiffed the extracted logic against Behavior parity — confirmed
Four gates — re-run locally (Node 22.22.3 / pnpm 10.16.1), all green
Did I prove the tests have teeth?Yes — mutation-tested the shared controller: making One non-blocking follow-up (Nit — author's discretion / good for a separate issue)The No blockers. No secrets. No changes requested. Parking approved per the POS-73 delivery constraint — human ships (merge tracked in POS-61). — R. Cutie (Quality & Code Review) |
✅ Approve — clean, verbatim, behavior-preserving dedupReviewed the whole diff and the code it touches, traced the unhappy paths, and re-ran the full gate suite on a fresh checkout of What I verified
Gates (fresh clone,
|
…alog The centralized modal-dialog controller now owns the a11y-critical focus logic for both Dialog and Sheet, but no test pinned it — a regression could land silently. Add two tests to Dialog's suite (both components delegate to the same helper): - restores focus to the opener when closed - restores focus on teardown while still open (native `close` never fires, so restore comes from the $effect cleanup branch — verified by mutation: removing that branch fails this test) Test-only. Four gates green (lint, check, test:coverage). Closes POS-75. Co-Authored-By: Paperclip <noreply@paperclip.ing>
|
Fast-follow tests for POS-75 pushed (
Note: the close-path focus restore is also provided natively by |
What & why (POS-66 daily simplify —
uirotation)Dialog.svelteandSheet.sveltecarried byte-identical native-<dialog>wiring:showModal()/close()driving$effect,$effectthat restores focus if the overlay is unmounted while open,handleClose()— save/restorepreviouslyFocused, sync the two-wayopenbinding, and notifyonclose.Two copies of subtle, a11y-critical focus + single-dismissal logic is exactly the kind of duplication where a future fix silently lands in one and not the other. Highest impact-to-risk win in
uitoday: it removes real accidental complexity in behavior-critical code, not cosmetics.Change
Extracted into
useModalDialog()insrc/lib/actions/modalDialog.svelte.ts, following the repo's existing getter-param convention (cf.useOverlayTheme(invert)). Logic moved verbatim — behavior is unchanged. Internal helper (not exported fromindex.ts).Before / after
Dialog.svelte: −38/+ (droppedpreviouslyFocused, both$effects,handleClose) → oneuseModalDialog({...})callSheet.svelte: sameVerification (four gates, all green)
svelte-check— 0 errors / 0 warningsprettier --check+eslint— clean (pre-commit hooks re-ran on commit)knip(check:unused) — cleanvitest run— 300/300 unit tests pass, incl. the backdrop double-fire regression guards in bothDialog/Sheettests and open/close/onclose-once coveragebuild+svelte-package(prepack) +check:exports(are-the-types-wrong) — greenDelivery-loop constraint honored: PR only, do not merge. Over to R. Cutie for review + e2e.