Commit 3180a714 authored by Rob Paveza's avatar Rob Paveza Committed by Commit Bot

DevTools: Accessibility issues with Elements - Properties

The Elements tool Properties pane is inaccessible via keyboard
only. It can't be tabbed into, and even if a user clicks into
it, the current selection top level tree branch can't be escaped.

This change addresses this issue by replacing the use of individual
ObjectPropertiesSection trees with an overarching
ObjectPropertiesSectionsTreeOutline, and then creating roots
for each of the objects being displayed. It also gives the OPSTO
a read-only mode (matching existing behavior) and enables tabbing
into the properties list.

GIF of after change: https://imgur.com/a/5Fi7W3h

Bug: 963183
Change-Id: I9c178c1d9758450196dd0596241047c9ea2dd813
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1757080
Commit-Queue: Robert Paveza <Rob.Paveza@microsoft.com>
Reviewed-by: default avatarYang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704844}
parent c0d2e457
......@@ -43,6 +43,16 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
SDK.DOMModel, SDK.DOMModel.Events.ChildNodeCountUpdated, this._onNodeChange, this);
UI.context.addFlavorChangeListener(SDK.DOMNode, this._setNode, this);
this._node = UI.context.flavor(SDK.DOMNode);
this._treeOutline = new ObjectUI.ObjectPropertiesSectionsTreeOutline({readOnly: true});
this._treeOutline.setShowSelectionOnKeyboardFocus(/* show */ true, /* preventTabOrder */ false);
this._expandController = new ObjectUI.ObjectPropertiesSectionsTreeExpandController(this._treeOutline);
this.contentElement.appendChild(this._treeOutline.element);
this._treeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, () => {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
});
this.update();
}
......@@ -67,7 +77,6 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
if (!this._node) {
this.contentElement.removeChildren();
this.sections = [];
return;
}
......@@ -92,15 +101,9 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
}
const properties = propertiesResult.properties;
const expanded = [];
const sections = this.sections || [];
for (let i = 0; i < sections.length; ++i) {
expanded.push(sections[i].expanded);
}
this.contentElement.removeChildren();
this.sections = [];
this._treeOutline.removeChildren();
let selected = false;
// Get array of property user-friendly names.
for (let i = 0; i < properties.length; ++i) {
if (!parseInt(properties[i].name, 10)) {
......@@ -109,14 +112,13 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
const property = properties[i].value;
let title = property.description;
title = title.replace(/Prototype$/, '');
const section = new ObjectUI.ObjectPropertiesSection(property, title);
section.element.classList.add('properties-widget-section');
this.sections.push(section);
this.contentElement.appendChild(section.element);
if (expanded[this.sections.length - 1]) {
section.expand();
const section = this._createSectionTreeElement(property, title);
this._treeOutline.appendChild(section);
if (!selected) {
section.select(/* omitFocus= */ true, /* selectedByUser= */ false);
selected = true;
}
section.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
}
/**
......@@ -136,13 +138,19 @@ Elements.PropertiesWidget = class extends UI.ThrottledWidget {
}
/**
* @param {!Common.Event} event
* @param {!SDK.RemoteObject} property
* @param {string} title
* @returns {!ObjectUI.ObjectPropertiesSection.RootElement}
*/
_propertyExpanded(event) {
Host.userMetrics.actionTaken(Host.UserMetrics.Action.DOMPropertiesExpanded);
for (const section of this.sections) {
section.removeEventListener(UI.TreeOutline.Events.ElementExpanded, this._propertyExpanded, this);
}
_createSectionTreeElement(property, title) {
const titleElement = createElementWithClass('span', 'tree-element-title');
titleElement.textContent = title;
const section = new ObjectUI.ObjectPropertiesSection.RootElement(property);
section.title = titleElement;
this._expandController.watchSection(title, section);
return section;
}
/**
......
......@@ -468,13 +468,22 @@ ObjectUI.ObjectPropertiesSection = class extends UI.TreeOutlineInShadow {
ObjectUI.ObjectPropertiesSection._arrayLoadThreshold = 100;
/** @const */
ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = 10000;
/**
* @typedef {{
* readOnly: (boolean|undefined),
* }}
*/
ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions;
ObjectUI.ObjectPropertiesSectionsTreeOutline = class extends UI.TreeOutlineInShadow {
constructor() {
/**
* @param {?ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions=} options
*/
constructor(options) {
super();
this.registerRequiredCSS('object_ui/objectValue.css');
this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
this._editable = true;
this._editable = !(options && options.readOnly);
this.contentElement.classList.add('source-code');
this.contentElement.classList.add('object-properties-section');
this.hideOverflow();
......
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