Commit 3d75e8ac authored by John Emau's avatar John Emau Committed by Commit Bot

DevTools: make quick open dialog announce screen reader options

This change expands existing screen reader capabilities of the quick
open dialog by replacing the use of aria alert with standard ARIA attributes:
role=combobox/listbox/option, aria-activedescendant, and aria-autocomplete.

The effect is the screen reader announces the selected options and their
position in the results, giving the user the total result count.

This change follows the WAI ARIA guidance:
https://www.w3.org/TR/wai-aria-1.1/#aria-autocomplete

Screenshot (NVDA Speech Viewer): https://i.imgur.com/4vJkHfq.png

Bug: 963183
Change-Id: I5c3b1b1f80c0a11defdfd66a4b6860df75e5e717
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1737872Reviewed-by: default avatarLorne Mitchell <lomitch@microsoft.com>
Commit-Queue: John Emau <John.Emau@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#706211}
parent dfc1f32e
...@@ -19,6 +19,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -19,6 +19,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this.contentElement.classList.add('filtered-list-widget'); this.contentElement.classList.add('filtered-list-widget');
this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), true); this.contentElement.addEventListener('keydown', this._onKeyDown.bind(this), true);
UI.ARIAUtils.markAsCombobox(this.contentElement);
this.registerRequiredCSS('quick_open/filteredListWidget.css'); this.registerRequiredCSS('quick_open/filteredListWidget.css');
this._promptElement = this.contentElement.createChild('div', 'filtered-list-widget-input'); this._promptElement = this.contentElement.createChild('div', 'filtered-list-widget-input');
...@@ -43,6 +44,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -43,6 +44,9 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this._itemElementsContainer.classList.add('container'); this._itemElementsContainer.classList.add('container');
this._bottomElementsContainer.appendChild(this._itemElementsContainer); this._bottomElementsContainer.appendChild(this._itemElementsContainer);
this._itemElementsContainer.addEventListener('click', this._onClick.bind(this), false); this._itemElementsContainer.addEventListener('click', this._onClick.bind(this), false);
UI.ARIAUtils.markAsListBox(this._itemElementsContainer);
UI.ARIAUtils.setControls(this._promptElement, this._itemElementsContainer);
UI.ARIAUtils.setAutocomplete(this._promptElement, 'list');
this._notFoundElement = this._bottomElementsContainer.createChild('div', 'not-found-text'); this._notFoundElement = this._bottomElementsContainer.createChild('div', 'not-found-text');
this._notFoundElement.classList.add('hidden'); this._notFoundElement.classList.add('hidden');
...@@ -113,6 +117,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -113,6 +117,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight); this._dialog.setSizeBehavior(UI.GlassPane.SizeBehavior.SetExactWidthMaxHeight);
this._dialog.setContentPosition(null, 22); this._dialog.setContentPosition(null, 22);
this.show(this._dialog.contentElement); this.show(this._dialog.contentElement);
UI.ARIAUtils.setExpanded(this.contentElement, true);
this._dialog.show(); this._dialog.show();
} }
...@@ -178,6 +183,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -178,6 +183,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
this._provider.detach(); this._provider.detach();
} }
this._clearTimers(); this._clearTimers();
UI.ARIAUtils.setExpanded(this.contentElement, false);
} }
_clearTimers() { _clearTimers() {
...@@ -232,6 +238,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -232,6 +238,7 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
const subtitleElement = itemElement.createChild('div', 'filtered-list-widget-subtitle'); const subtitleElement = itemElement.createChild('div', 'filtered-list-widget-subtitle');
subtitleElement.textContent = '\u200B'; subtitleElement.textContent = '\u200B';
this._provider.renderItem(item, this._cleanValue(), titleElement, subtitleElement); this._provider.renderItem(item, this._cleanValue(), titleElement, subtitleElement);
UI.ARIAUtils.markAsOption(itemElement);
return itemElement; return itemElement;
} }
...@@ -267,8 +274,8 @@ QuickOpen.FilteredListWidget = class extends UI.VBox { ...@@ -267,8 +274,8 @@ QuickOpen.FilteredListWidget = class extends UI.VBox {
} }
if (toElement) { if (toElement) {
toElement.classList.add('selected'); toElement.classList.add('selected');
UI.ARIAUtils.alert(toElement.textContent, toElement);
} }
UI.ARIAUtils.setActiveDescendant(this._promptElement, toElement);
} }
/** /**
......
...@@ -44,6 +44,13 @@ export function markAsCheckbox(element) { ...@@ -44,6 +44,13 @@ export function markAsCheckbox(element) {
element.setAttribute('role', 'checkbox'); element.setAttribute('role', 'checkbox');
} }
/**
* @param {!Element} element
*/
export function markAsCombobox(element) {
element.setAttribute('role', 'combobox');
}
/** /**
* @param {!Element} element * @param {!Element} element
*/ */
...@@ -281,6 +288,14 @@ export function unsetExpandable(element) { ...@@ -281,6 +288,14 @@ export function unsetExpandable(element) {
element.removeAttribute('aria-expanded'); element.removeAttribute('aria-expanded');
} }
/**
* @param {!Element} element
* @param {string} interactionModel can be 'inline', 'list', 'both' or 'none' (default).
*/
export function setAutocomplete(element, interactionModel = 'none') {
element.setAttribute('aria-autocomplete', interactionModel);
}
/** /**
* @param {!Element} element * @param {!Element} element
* @param {boolean} value * @param {boolean} value
...@@ -476,6 +491,7 @@ self.UI.ARIAUtils = { ...@@ -476,6 +491,7 @@ self.UI.ARIAUtils = {
markAsAlert, markAsAlert,
markAsButton, markAsButton,
markAsCheckbox, markAsCheckbox,
markAsCombobox,
markAsModalDialog, markAsModalDialog,
markAsGroup, markAsGroup,
markAsLink, markAsLink,
...@@ -506,6 +522,7 @@ self.UI.ARIAUtils = { ...@@ -506,6 +522,7 @@ self.UI.ARIAUtils = {
setCheckboxAsIndeterminate, setCheckboxAsIndeterminate,
setExpanded, setExpanded,
unsetExpandable, unsetExpandable,
setAutocomplete,
setSelected, setSelected,
setInvalid, setInvalid,
setPressed, setPressed,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment