Skip to content

Commit

Permalink
Handle entering FocusWrap from outside (#3641)
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 authored Jan 18, 2025
1 parent ee8602e commit d94b69c
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 d94b69c

Please sign in to comment.