-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Popover ] Fixed incorrect element being focused when closed #2255
Conversation
1717d92
to
6d89db1
Compare
src/utilities/focus.ts
Outdated
let nextElement = node.nextElementSibling; | ||
|
||
while (nextElement) { | ||
if (nextElement.matches(FOCUSABLE_SELECTOR)) return nextElement; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going with the matches
approach that rather a tabIndex so we can ignore disabled elements
src/utilities/focus.ts
Outdated
while (nextElement) { | ||
if (nextElement.matches(FOCUSABLE_SELECTOR)) return nextElement; | ||
|
||
if (nextElement instanceof HTMLElement) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
findFirstFocusableNode require HTMLElement
rather than Element
. Although nextElementSibling
won't return text nodes so I'm not sure we'll ever get an Element
|
||
export function focusNextFocusableNode(node: HTMLElement) { | ||
const nextFocusable = nextFocusableNode(node); | ||
if (nextFocusable && nextFocusable instanceof HTMLElement) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The Element
interface doesn't contain focus
so we need this check
const nextFocusable = nextFocusableNode(node); | ||
if (nextFocusable && nextFocusable instanceof HTMLElement) { | ||
nextFocusable.focus(); | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added a boolean return rather than void so we can determine if an element was focused or not
6d89db1
to
e89834c
Compare
src/utilities/focus.ts
Outdated
export function nextFocusableNode( | ||
node: HTMLElement, | ||
): HTMLElement | Element | null { | ||
let nextElement = node.nextElementSibling; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic will only work if the nextFocusableElement same tree level or lower correct? The following would not pass
<React.Fragment>
<div><Popover active activator={<div />} onClose={noop} /></div>
<button id={id} />
</React.Fragment>
I think it's fine since the activator will get focus in the end. I can't think of an inexpensive way to do this either. What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is a new issue or not (since our previous examples didn't have additional elements to manage focus around, but I found while testing this that focus is does not appear to be moved to the popover on iOS when the button is activated. When using VoiceOver with Safari or Chrome on iOS, I had to swipe to the next focusable target
button before I could swipe to the popover contents. Can we confirm if this was an existing issue, or if it's introduced by this update? If it's not new, I'll open a new issue, which we should address as soon as possible, since it impacts popover usage across mobile.
I wonder if we can also take a look at web
to see if anyone is overriding our current focus management logic for popovers, to make sure this update won't cause conflicts?
0ba6a36
to
4b255bb
Compare
@dleroux and I spent some time on iOS voiceover and it appears it's an existing issue. Oddly enough we still have the correct focus order, however it seems voice was following the dom order, and not respecting the currently focused element. Is this many a voiceover bug?
It would be pretty difficult to check all the popovers since there're hundreds, maybe thousands 😬 however I tested home, and a few other pages as well and everything looked 👍 |
Created issue #2387 to capture the issue with VoiceOver on iOS. |
Is this ready to review again @AndrewMusgrave? |
@dleroux Per discussion in Slack last week, yes! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎩 and works great.
Interestingly enough as I was tabbing through the popover I would have expected it to trap focus but I'm guessing that is not the case? @dpersing
node: HTMLElement, | ||
filter?: Filter, | ||
): HTMLElement | Element | null { | ||
const allFocusableElements = [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
}); | ||
}); | ||
|
||
function domSetup( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is great, not asking to change it, but I wonder if it wouldn't have been simpler outline the dom being tested with each test. It makes it a little tricky to review and it's almost like domSetup()
needs its own tests.
4b255bb
to
9894f68
Compare
WHY are these changes introduced?
Fixes #2188
WHAT is this pull request doing?
How to 🎩
With another focusable element
Without another focusable element
TODO
🎩 checklist
README.md
with documentation changes