-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
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
[Autocomplete] Fix aria-controls and aria-activedescendant #18142
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -104,7 +104,10 @@ export default function useAutocomplete(props) { | |
|
||
function setHighlightedIndex(index, mouse = false) { | ||
highlightedIndexRef.current = index; | ||
inputRef.current.setAttribute('aria-activedescendant', `${id}-option-${index}`); | ||
// does the index exist? | ||
if (index !== -1) { | ||
inputRef.current.setAttribute('aria-activedescendant', `${id}-option-${index}`); | ||
eps1lon marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
if (!listboxRef.current) { | ||
return; | ||
|
@@ -650,8 +653,11 @@ export default function useAutocomplete(props) { | |
onBlur: handleBlur, | ||
onFocus: handleFocus, | ||
onChange: handleInputChange, | ||
// if open then this is handled imperativeley so don't let react override | ||
// only have an opinion about this when closed | ||
'aria-activedescendant': popupOpen ? undefined : null, | ||
'aria-autocomplete': autoComplete ? 'both' : 'list', | ||
'aria-controls': `${id}-listbox`, | ||
'aria-controls': `${id}-popup`, | ||
// autoComplete: 'off', // Disable browser's suggestion that might overlap with the popup. | ||
autoComplete: 'disabled', // disable autocomplete and autofill | ||
ref: inputRef, | ||
|
@@ -678,11 +684,10 @@ export default function useAutocomplete(props) { | |
}), | ||
getPopupProps: () => ({ | ||
role: 'presentation', | ||
id: `${id}-popup`, | ||
}), | ||
getListboxProps: () => ({ | ||
role: 'listbox', | ||
id: `${id}-listbox`, | ||
id: `${id}-popup`, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the role of this element is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The popup is the generic term for the "list" of possible items. It can also be a grid or tree. It makes more sense if you look at the aria-controls which doesn't care if you have a listbox or grid or tree. Just that the element in question is the popup with the possible items. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems correct, oops 🙃. What do you think of killing the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why Popup to Popper? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought that the popup was a different element to the listbox. As you raised it out, it's not. Because the default value for PopupComponent is a Popper, the change could make the API more intuitive. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah that makes sense. |
||
'aria-labelledby': `${id}-label`, | ||
ref: handleListboxRef, | ||
onMouseDown: event => { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
diff --git a/node_modules/jsdom/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js b/node_modules/jsdom/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js | ||
index 468f263..2ef0288 100644 | ||
--- a/node_modules/jsdom/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js | ||
+++ b/node_modules/jsdom/lib/jsdom/living/nodes/HTMLOrSVGElement-impl.js | ||
@@ -45,6 +45,10 @@ class HTMLOrSVGElementImpl { | ||
|
||
const previous = this._ownerDocument._lastFocusedElement; | ||
|
||
+ if (previous === this) { | ||
+ return; | ||
+ } | ||
+ | ||
focusing.fireFocusEventWithTargetAdjustment("blur", previous, this); | ||
this._ownerDocument._lastFocusedElement = this; | ||
focusing.fireFocusEventWithTargetAdjustment("focus", this, previous); |
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 will be called twice with jsdom actual because the implementation includes a .focus() noop that causes jsdom to fire a blur event which also calls onClose. In the browser this will work correctly.