-
Notifications
You must be signed in to change notification settings - Fork 11
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
Fix autocomplete keyboard control on Windows/Edge #170
Changes from 4 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -16,10 +16,6 @@ const CLASSNAMES = { | |||||
NO_RESULTS: 'radar-no-results', | ||||||
}; | ||||||
|
||||||
const ARIA = { | ||||||
EXPANDED: 'aria-expanded', | ||||||
}; | ||||||
|
||||||
const defaultAutocompleteOptions: RadarAutocompleteUIOptions = { | ||||||
container: 'autocomplete', | ||||||
debounceMS: 200, // Debounce time in milliseconds | ||||||
|
@@ -136,6 +132,10 @@ class AutocompleteUI { | |||||
// result list element | ||||||
this.resultsList = document.createElement('ul'); | ||||||
this.resultsList.classList.add(CLASSNAMES.RESULTS_LIST); | ||||||
this.resultsList.classList.add('id', CLASSNAMES.RESULTS_LIST); | ||||||
this.resultsList.setAttribute('role', 'listbox'); | ||||||
this.resultsList.setAttribute('aria-live', 'polite'); | ||||||
this.resultsList.setAttribute('aria-label', 'Search results'); | ||||||
setHeight(this.resultsList, this.config); | ||||||
|
||||||
if (containerEL.nodeName === 'INPUT') { | ||||||
|
@@ -168,6 +168,14 @@ class AutocompleteUI { | |||||
this.container.appendChild(this.wrapper); | ||||||
} | ||||||
|
||||||
// set aria roles | ||||||
this.inputField.setAttribute('role', 'combobox'); | ||||||
this.inputField.setAttribute('aria-controls', CLASSNAMES.RESULTS_LIST); | ||||||
this.inputField.setAttribute('aria-expanded', 'false'); | ||||||
this.inputField.setAttribute('aria-haspopup', 'listbox'); | ||||||
this.inputField.setAttribute('aria-autocomplete', 'list'); | ||||||
this.inputField.setAttribute('aria-activedescendant', ''); | ||||||
|
||||||
// setup event listeners | ||||||
this.inputField.addEventListener('input', this.handleInput.bind(this)); | ||||||
this.inputField.addEventListener('keydown', this.handleKeyboardNavigation.bind(this)); | ||||||
|
@@ -275,6 +283,8 @@ class AutocompleteUI { | |||||
results.forEach((result, index) => { | ||||||
const li = document.createElement('li'); | ||||||
li.classList.add(CLASSNAMES.RESULTS_ITEM); | ||||||
li.setAttribute('role', 'option'); | ||||||
li.setAttribute('id', `item-${index}`); | ||||||
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. fyi we use the same
Suggested change
to make it more consistent? 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. we should prob make this |
||||||
|
||||||
// construct result with bolded label | ||||||
let listContent; | ||||||
|
@@ -336,7 +346,7 @@ class AutocompleteUI { | |||||
return; | ||||||
} | ||||||
|
||||||
this.wrapper.setAttribute(ARIA.EXPANDED, 'true'); | ||||||
this.inputField.setAttribute('aria-expanded', 'true'); | ||||||
this.resultsList.removeAttribute('hidden'); | ||||||
this.isOpen = true; | ||||||
} | ||||||
|
@@ -350,7 +360,8 @@ class AutocompleteUI { | |||||
// (add 100ms delay if closed from link click) | ||||||
const linkClick = e && (e.relatedTarget === this.poweredByLink); | ||||||
setTimeout(() => { | ||||||
this.wrapper.removeAttribute(ARIA.EXPANDED); | ||||||
this.inputField.setAttribute('aria-expanded', 'false'); | ||||||
this.inputField.setAttribute('aria-activedescendant', ''); | ||||||
this.resultsList.setAttribute('hidden', ''); | ||||||
this.highlightedIndex = -1; | ||||||
this.isOpen = false; | ||||||
|
@@ -380,43 +391,41 @@ class AutocompleteUI { | |||||
// add class name to newly highlighted item | ||||||
resultItems[index].classList.add(CLASSNAMES.SELECTED_ITEM); | ||||||
|
||||||
// set aria active descendant | ||||||
this.inputField.setAttribute('aria-activedescendant', `item-${index}`); | ||||||
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. and if we wanna go with the above suggestion
Suggested change
|
||||||
|
||||||
this.highlightedIndex = index; | ||||||
} | ||||||
|
||||||
public handleKeyboardNavigation(event: KeyboardEvent) { | ||||||
// fallback to deprecated "keyCode" if event.code not set | ||||||
const code = event.code !== undefined ? event.code : event.keyCode; | ||||||
const key = event.key; | ||||||
|
||||||
// allow event to propagate if result list is not open | ||||||
if (!this.isOpen) { | ||||||
return; | ||||||
} | ||||||
|
||||||
switch (code) { | ||||||
switch (key) { | ||||||
// Next item | ||||||
case 'Tab': | ||||||
case 'ArrowDown': | ||||||
case 40: | ||||||
event.preventDefault(); | ||||||
this.goTo(this.highlightedIndex + 1); | ||||||
break; | ||||||
|
||||||
// Prev item | ||||||
case 'ArrowUp': | ||||||
case 38: | ||||||
event.preventDefault(); | ||||||
this.goTo(this.highlightedIndex - 1); | ||||||
break; | ||||||
|
||||||
// Select | ||||||
case 'Enter': | ||||||
case 13: | ||||||
this.select(this.highlightedIndex); | ||||||
break; | ||||||
|
||||||
// Close | ||||||
case 'Esc': | ||||||
case 27: | ||||||
this.close(); | ||||||
break; | ||||||
} | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
export default '4.3.0'; | ||
export default '4.3.1-beta.2'; |
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.