Commit df409599 authored by Jack Lynch's avatar Jack Lynch Committed by Commit Bot

DevTools: Make event listener breakpoints keyboard-navigable

This change makes the event listeners pane navigable by keyboard and
accessible to screen readers.

Standard treeoutline keyboard focus is the only visible change:
https://gyazo.com/0098dd06216f58575468fcf7c5902cbc

Keyboard navigation video: https://i.imgur.com/Hq73jum.mp4

Bug: 963183
Change-Id: Ia32451e29b16a63e20de0a1e6c351e38568c13ba
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1649732Reviewed-by: default avatarLorne Mitchell <lomitch@microsoft.com>
Commit-Queue: Jack Lynch <jalyn@microsoft.com>
Cr-Commit-Position: refs/heads/master@{#706565}
parent b88db346
...@@ -8,8 +8,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -8,8 +8,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
constructor() { constructor() {
super(true); super(true);
this._categoriesTreeOutline = new UI.TreeOutlineInShadow(); this._categoriesTreeOutline = new UI.TreeOutlineInShadow();
this._categoriesTreeOutline.element.tabIndex = 0;
this._categoriesTreeOutline.registerRequiredCSS('browser_debugger/eventListenerBreakpoints.css'); this._categoriesTreeOutline.registerRequiredCSS('browser_debugger/eventListenerBreakpoints.css');
this._categoriesTreeOutline.setShowSelectionOnKeyboardFocus(/* show */ true);
this.contentElement.appendChild(this._categoriesTreeOutline.element); this.contentElement.appendChild(this._categoriesTreeOutline.element);
/** @type {!Map<string, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */ /** @type {!Map<string, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */
...@@ -21,6 +21,10 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -21,6 +21,10 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
this._createCategory(category); this._createCategory(category);
} }
} }
if (categories.length > 0) {
const firstCategory = this._categories.get(categories[0]);
firstCategory.element.select();
}
/** @type {!Map<!SDK.DOMDebuggerModel.EventListenerBreakpoint, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */ /** @type {!Map<!SDK.DOMDebuggerModel.EventListenerBreakpoint, !BrowserDebugger.EventListenerBreakpointsSidebarPane.Item>} */
this._breakpoints = new Map(); this._breakpoints = new Map();
...@@ -33,15 +37,29 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -33,15 +37,29 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
UI.context.addFlavorChangeListener(SDK.Target, this._update, this); UI.context.addFlavorChangeListener(SDK.Target, this._update, this);
} }
/**
* @override
*/
focus() {
this._categoriesTreeOutline.forceSelect();
}
/** /**
* @param {string} name * @param {string} name
*/ */
_createCategory(name) { _createCategory(name) {
const labelNode = UI.CheckboxLabel.create(name); const labelNode = UI.CheckboxLabel.create(name);
labelNode.checkboxElement.addEventListener('click', this._categoryCheckboxClicked.bind(this, name), true); labelNode.checkboxElement.addEventListener('click', this._categoryCheckboxClicked.bind(this, name), true);
labelNode.checkboxElement.tabIndex = -1;
const treeElement = new UI.TreeElement(labelNode); const treeElement = new UI.TreeElement(labelNode);
treeElement.selectable = false; treeElement.listItemElement.addEventListener('keydown', event => {
if (event.key === ' ') {
this._categories.get(name).checkbox.click();
event.consume(true);
}
});
UI.ARIAUtils.setChecked(treeElement.listItemElement, false);
this._categoriesTreeOutline.appendChild(treeElement); this._categoriesTreeOutline.appendChild(treeElement);
this._categories.set(name, {element: treeElement, checkbox: labelNode.checkboxElement}); this._categories.set(name, {element: treeElement, checkbox: labelNode.checkboxElement});
...@@ -54,10 +72,17 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -54,10 +72,17 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
const labelNode = UI.CheckboxLabel.create(breakpoint.title()); const labelNode = UI.CheckboxLabel.create(breakpoint.title());
labelNode.classList.add('source-code'); labelNode.classList.add('source-code');
labelNode.checkboxElement.addEventListener('click', this._breakpointCheckboxClicked.bind(this, breakpoint), true); labelNode.checkboxElement.addEventListener('click', this._breakpointCheckboxClicked.bind(this, breakpoint), true);
labelNode.checkboxElement.tabIndex = -1;
const treeElement = new UI.TreeElement(labelNode); const treeElement = new UI.TreeElement(labelNode);
treeElement.listItemElement.addEventListener('keydown', event => {
if (event.key === ' ') {
this._breakpoints.get(breakpoint).checkbox.click();
event.consume(true);
}
});
UI.ARIAUtils.setChecked(treeElement.listItemElement, false);
treeElement.listItemElement.createChild('div', 'breakpoint-hit-marker'); treeElement.listItemElement.createChild('div', 'breakpoint-hit-marker');
treeElement.selectable = false;
this._categories.get(breakpoint.category()).element.appendChild(treeElement); this._categories.get(breakpoint.category()).element.appendChild(treeElement);
this._breakpoints.set(breakpoint, {element: treeElement, checkbox: labelNode.checkboxElement}); this._breakpoints.set(breakpoint, {element: treeElement, checkbox: labelNode.checkboxElement});
...@@ -70,6 +95,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -70,6 +95,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
if (!details || details.reason !== SDK.DebuggerModel.BreakReason.EventListener || !details.auxData) { if (!details || details.reason !== SDK.DebuggerModel.BreakReason.EventListener || !details.auxData) {
if (this._highlightedElement) { if (this._highlightedElement) {
UI.ARIAUtils.setDescription(this._highlightedElement, '');
this._highlightedElement.classList.remove('breakpoint-hit'); this._highlightedElement.classList.remove('breakpoint-hit');
delete this._highlightedElement; delete this._highlightedElement;
} }
...@@ -84,6 +110,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -84,6 +110,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
UI.viewManager.showView('sources.eventListenerBreakpoints'); UI.viewManager.showView('sources.eventListenerBreakpoints');
this._categories.get(breakpoint.category()).element.expand(); this._categories.get(breakpoint.category()).element.expand();
this._highlightedElement = this._breakpoints.get(breakpoint).element.listItemElement; this._highlightedElement = this._breakpoints.get(breakpoint).element.listItemElement;
UI.ARIAUtils.setDescription(this._highlightedElement, ls`breakpoint hit`);
this._highlightedElement.classList.add('breakpoint-hit'); this._highlightedElement.classList.add('breakpoint-hit');
} }
...@@ -93,6 +120,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -93,6 +120,8 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
_categoryCheckboxClicked(category) { _categoryCheckboxClicked(category) {
const item = this._categories.get(category); const item = this._categories.get(category);
const enabled = item.checkbox.checked; const enabled = item.checkbox.checked;
UI.ARIAUtils.setChecked(item.element.listItemElement, enabled);
for (const breakpoint of this._breakpoints.keys()) { for (const breakpoint of this._breakpoints.keys()) {
if (breakpoint.category() === category) { if (breakpoint.category() === category) {
breakpoint.setEnabled(enabled); breakpoint.setEnabled(enabled);
...@@ -107,6 +136,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -107,6 +136,7 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
_breakpointCheckboxClicked(breakpoint) { _breakpointCheckboxClicked(breakpoint) {
const item = this._breakpoints.get(breakpoint); const item = this._breakpoints.get(breakpoint);
breakpoint.setEnabled(item.checkbox.checked); breakpoint.setEnabled(item.checkbox.checked);
UI.ARIAUtils.setChecked(item.element.listItemElement, item.checkbox.checked);
let hasEnabled = false; let hasEnabled = false;
let hasDisabled = false; let hasDisabled = false;
...@@ -120,9 +150,14 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox { ...@@ -120,9 +150,14 @@ BrowserDebugger.EventListenerBreakpointsSidebarPane = class extends UI.VBox {
} }
} }
const checkbox = this._categories.get(breakpoint.category()).checkbox; const category = this._categories.get(breakpoint.category());
checkbox.checked = hasEnabled; category.checkbox.checked = hasEnabled;
checkbox.indeterminate = hasEnabled && hasDisabled; category.checkbox.indeterminate = hasEnabled && hasDisabled;
if (category.checkbox.indeterminate) {
UI.ARIAUtils.setCheckboxAsIndeterminate(category.element.listItemElement);
} else {
UI.ARIAUtils.setChecked(category.element.listItemElement, hasEnabled);
}
} }
}; };
......
...@@ -12,6 +12,9 @@ ...@@ -12,6 +12,9 @@
<message name="IDS_DEVTOOLS_39c145d69ad05e44e74017346c116251" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel"> <message name="IDS_DEVTOOLS_39c145d69ad05e44e74017346c116251" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Remove all DOM breakpoints Remove all DOM breakpoints
</message> </message>
<message name="IDS_DEVTOOLS_3ea566249a507705d9a7ff4d3bd31440" desc="Screen reader description of a hit breakpoint in the Sources panel">
breakpoint hit
</message>
<message name="IDS_DEVTOOLS_59eaf6955f44a94237b6d26911c1d983" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel"> <message name="IDS_DEVTOOLS_59eaf6955f44a94237b6d26911c1d983" desc="A context menu item in the DOMBreakpoints Sidebar Pane of the JavaScript Debugging pane in the Sources panel or the DOM Breakpoints pane in the Elements panel">
Break on Break on
</message> </message>
......
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