a11y(2.4.3): focus-trap — capture and restore focus to the trigger element on close#3536
Open
rosanusi wants to merge 2 commits into
Open
a11y(2.4.3): focus-trap — capture and restore focus to the trigger element on close#3536rosanusi wants to merge 2 commits into
rosanusi wants to merge 2 commits into
Conversation
…t on close Keyboard users who open a Modal/Drawer/Maximizable and close it via Escape had focus fall to document.body, forcing full re-navigation. Fix captures document.activeElement before first focus() call and restores it in cleanUp(). The MutationObserver path (DOM changes inside the trap) now calls removeListeners() directly instead of cleanUp() to avoid incorrectly restoring focus on in-trap content changes. Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes WCAG 2.2 SC 2.4.3 (Focus Order) in
src/lib/utilities/focus-trap.ts. The shared focus-trap Svelte action — consumed byModal,Drawer,Maximizable, and the command-paletteModal— trapped Tab correctly but never captured the pre-activation focus position, so closing any of these surfaces dropped focus todocument.body. Keyboard users lost their place in the page on every modal/drawer close.Three gaps closed:
No capture —
setFocus()now recordsdocument.activeElementintopreviouslyFocusedbefore callingfirstFocusable.focus(), but only on first activation (previouslyFocused === null) and not on MutationObserver re-runs (fromObserver=true), so in-trap DOM changes do not clobber the original trigger.No restore on deactivate —
cleanUp()now callspreviouslyFocused.focus()(guarded bydocument.body.contains()in case the trigger was removed from the DOM while the trap was open) and then resetspreviouslyFocused = nullso re-enabling captures fresh.MutationObserver path fixed —
onChangepreviously calledcleanUp()on every DOM mutation inside the trap, which would have triggered premature focus restoration after this change. ExtractedremoveListeners()(listener teardown only) and changedonChangeto call that instead ofcleanUp().Consumers updated automatically (no per-file change needed):
src/lib/holocene/modal.svelte(use:focusTrap={true})src/lib/holocene/drawer.svelte(use:focusTrap={true})src/lib/holocene/maximizable/maximizable.svelte(use:focusTrap={maximized})src/lib/components/command-palette/modal.svelte(use:focusTrap={true})Primitive-level fix cascades to cloud-ui-main on tarball repack.
Screenshots
No visual change. The fix affects keyboard focus position after closing a modal or drawer.
Design
N/A.
Testing
Cmd+Kfrom any page → Tab into results → press Escape. Confirm focus returns to the previously focused element.Checklist
Docs
No documentation changes required.
A11y-Audit-Ref: 2.4.3-focus-restoration-on-close