Skip to content

Commit

Permalink
Handle entering FocusWrap from outside
Browse files Browse the repository at this point in the history
When FocusWrap was used, but the previous focus was outside of the wrapped
element, the browser would try to focus the boundary element, causing us
to focus the last element instead. This is fixed by checking the relatedTarget
of the event, and specially handling focus coming from outside.

Fixes #3636.
  • Loading branch information
SteffenDE committed Jan 18, 2025
1 parent 8df189a commit 3befdff
Showing 1 changed file with 20 additions and 2 deletions.
22 changes: 20 additions & 2 deletions assets/js/phoenix_live_view/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,26 @@ let Hooks = {
mounted(){
this.focusStart = this.el.firstElementChild
this.focusEnd = this.el.lastElementChild
this.focusStart.addEventListener("focus", () => ARIA.focusLast(this.el))
this.focusEnd.addEventListener("focus", () => ARIA.focusFirst(this.el))
this.focusStart.addEventListener("focus", (e) => {
if(!e.relatedTarget || !this.el.contains(e.relatedTarget)){
// Handle focus entering from outside (e.g. Tab when body is focused)
// https://github.com/phoenixframework/phoenix_live_view/issues/3636
const nextFocus = e.target.nextElementSibling
ARIA.attemptFocus(nextFocus) || ARIA.focusFirst(nextFocus)
} else {
ARIA.focusLast(this.el)
}
})
this.focusEnd.addEventListener("focus", (e) => {
if(!e.relatedTarget || !this.el.contains(e.relatedTarget)){
// Handle focus entering from outside (e.g. Shift+Tab when body is focused)
// https://github.com/phoenixframework/phoenix_live_view/issues/3636
const nextFocus = e.target.previousElementSibling
ARIA.attemptFocus(nextFocus) || ARIA.focusLast(nextFocus)
} else {
ARIA.focusFirst(this.el)
}
})
this.el.addEventListener("phx:show-end", () => this.el.focus())
if(window.getComputedStyle(this.el).display !== "none"){
ARIA.focusFirst(this.el)
Expand Down

0 comments on commit 3befdff

Please sign in to comment.