Skip to content

refactor(website): make confirmation dialog a global singleton#6789

Merged
corneliusroemer merged 2 commits into
unify-modalfrom
confirmation
Jun 29, 2026
Merged

refactor(website): make confirmation dialog a global singleton#6789
corneliusroemer merged 2 commits into
unify-modalfrom
confirmation

Conversation

@theosanderson

@theosanderson theosanderson commented Jun 29, 2026

Copy link
Copy Markdown
Member

PR to Cornelius's PR #6780

Replace the useConfirmDialog() hook (which returned { confirm, confirmDialog } and required every call site to both call confirm() and render {confirmDialog}) with a module-level store and a single ConfirmDialogContainer host mounted once in BaseLayout. Call sites now just import and call confirm() — no element to render, and no risk of an early return omitting the dialog.

A module-level store rather than React context is required because each Astro client:* island is an isolated React tree that context cannot cross. The host renders in-tree (not a detached createRoot), so Headless UI still makes the background inert and traps focus.

🚀 Preview: https://confirmation.loculus.org

Replace the useConfirmDialog() hook (which returned { confirm, confirmDialog }
and required every call site to both call confirm() and render {confirmDialog})
with a module-level store and a single ConfirmDialogContainer host mounted once
in BaseLayout. Call sites now just import and call confirm() — no element to
render, and no risk of an early return omitting the dialog.

A module-level store rather than React context is required because each Astro
client:* island is an isolated React tree that context cannot cross. The host
renders in-tree (not a detached createRoot), so Headless UI still makes the
background inert and traps focus.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@theosanderson theosanderson added the preview Triggers a deployment to argocd label Jun 29, 2026
@claude claude Bot added the website Tasks related to the web application label Jun 29, 2026
@claude

claude Bot commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

This PR may be related to: #6744 (Confirmation dialogs/modals should make background greyed out items inert for keyboard navigation) — the PR description notes that the new in-tree host means Headless UI still makes the background inert and traps focus, which directly addresses the accessibility concern raised in that issue.

@corneliusroemer

corneliusroemer commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Very nice, tested locally and works 🎉

Just the tests now are unhappy:


Error: TestingLibraryElementError: Unable to find role="button" and name "Continue under Open terms"

Ignored nodes: comments, script, 

@theosanderson

Copy link
Copy Markdown
Member Author

yep working on it, thanks!

The confirmation dialog now renders via a single global host (in BaseLayout),
so components calling displayConfirmation() no longer render the dialog
themselves. Mount ConfirmDialogContainer alongside the component in the specs
that exercise confirm flows (ReviewPage, SubmissionForm, FolderUploadComponent).

Also reset the dialog store when the last host unsubscribes, so module state
cannot leak between tests that remount the host. In the app the single host
lives for the whole session, so this never fires there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@theosanderson

Copy link
Copy Markdown
Member Author

annoying amount of churn to supply this for the tests - I tried a global pattern where one wouldn't have needed changes for each test but that broke the hydrated button test. I think that possibly indicates that that test is overly fragile. Anyway, I'd be very keen to keep this single-function pattern one way or another.

@corneliusroemer

Copy link
Copy Markdown
Contributor

Not so worried about the test churn. The global state outside React isn't great but if you want the DX of single call I'm fine with it.

@theosanderson

Copy link
Copy Markdown
Member Author

This is the pattern we already have for toasts, and I do think it's significantly safer. Thanks for tolerating!

@corneliusroemer corneliusroemer merged commit 2ff70fe into unify-modal Jun 29, 2026
38 of 39 checks passed
@corneliusroemer corneliusroemer deleted the confirmation branch June 29, 2026 14:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Triggers a deployment to argocd website Tasks related to the web application

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants