Commit d59f3187 authored by Patrick Hulce's avatar Patrick Hulce Committed by Commit Bot

DevTools: Audits2 UI Polish

- Convert dropdowns to radio/checkbox inputs
- Resize icons/line height/padding
- Overlay size fix
- Minor typographic adjustments
- Disable start audit button when on active view

BUG=844331,844334,844374,844352,844324,844318

Change-Id: Ieb87ce0994031c69a260bddf83f8ad995c8ea70c
Reviewed-on: https://chromium-review.googlesource.com/1066302
Commit-Queue: Patrick Hulce <phulce@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#561332}
parent 965042c5
...@@ -7,7 +7,8 @@ Tests that audits panel works when only performance category is selected. ...@@ -7,7 +7,8 @@ Tests that audits panel works when only performance category is selected.
[ ] Best practices [ ] Best practices
[ ] Accessibility [ ] Accessibility
[ ] SEO [ ] SEO
Run audit: enabled visible [x] Clear storage
Run audits: enabled visible
=============== Lighthouse Results =============== =============== Lighthouse Results ===============
bootup-time: true bootup-time: true
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
var dialogElement = Audits2TestRunner.getContainerElement(); var dialogElement = Audits2TestRunner.getContainerElement();
var checkboxes = dialogElement.querySelectorAll('.checkbox'); var checkboxes = dialogElement.querySelectorAll('.checkbox');
for (var checkbox of checkboxes) { for (var checkbox of checkboxes) {
if (checkbox.textElement.textContent === 'Performance') if (checkbox.textElement.textContent === 'Performance' ||
checkbox.textElement.textContent === 'Clear storage')
continue; continue;
checkbox.checkboxElement.click(); checkbox.checkboxElement.click();
......
...@@ -8,8 +8,9 @@ Tests that audits panel prevents run of unauditable pages. ...@@ -8,8 +8,9 @@ Tests that audits panel prevents run of unauditable pages.
[ ] Best practices [ ] Best practices
[ ] Accessibility [ ] Accessibility
[ ] SEO [ ] SEO
[ ] Clear storage
Help text: At least one category must be selected. Help text: At least one category must be selected.
Run audit: disabled visible Run audits: disabled visible
**Allows audit with a single category** **Allows audit with a single category**
========== Audits2 Start Audit State ========== ========== Audits2 Start Audit State ==========
...@@ -18,7 +19,8 @@ Run audit: disabled visible ...@@ -18,7 +19,8 @@ Run audit: disabled visible
[ ] Best practices [ ] Best practices
[ ] Accessibility [ ] Accessibility
[ ] SEO [ ] SEO
Run audit: enabled visible [ ] Clear storage
Run audits: enabled visible
**Prevents audit on undockable page** **Prevents audit on undockable page**
========== Audits2 Start Audit State ========== ========== Audits2 Start Audit State ==========
...@@ -27,8 +29,9 @@ Run audit: enabled visible ...@@ -27,8 +29,9 @@ Run audit: enabled visible
[ ] Best practices [ ] Best practices
[ ] Accessibility [ ] Accessibility
[ ] SEO [ ] SEO
[ ] Clear storage
Help text: Can only audit tabs. Navigate to this page in a separate tab to start an audit. Help text: Can only audit tabs. Navigate to this page in a separate tab to start an audit.
Run audit: disabled visible Run audits: disabled visible
**Prevents audit on internal page** **Prevents audit on internal page**
URL: about:blank URL: about:blank
...@@ -38,6 +41,7 @@ URL: about:blank ...@@ -38,6 +41,7 @@ URL: about:blank
[ ] Best practices [ ] Best practices
[ ] Accessibility [ ] Accessibility
[ ] SEO [ ] SEO
[ ] Clear storage
Help text: Can only audit HTTP/HTTPS pages and Chrome extensions. Navigate to a different page to start an audit. Help text: Can only audit HTTP/HTTPS pages and Chrome extensions. Navigate to a different page to start an audit.
Run audit: disabled visible Run audits: disabled visible
...@@ -7,7 +7,8 @@ Tests that audits panel works. ...@@ -7,7 +7,8 @@ Tests that audits panel works.
[x] Best practices [x] Best practices
[x] Accessibility [x] Accessibility
[x] SEO [x] SEO
Run audit: enabled visible [x] Clear storage
Run audits: enabled visible
=============== Lighthouse Status Updates =============== =============== Lighthouse Status Updates ===============
Loading… Loading…
......
...@@ -50,6 +50,7 @@ all_devtools_files = [ ...@@ -50,6 +50,7 @@ all_devtools_files = [
"front_end/audits2/audits2Dialog.css", "front_end/audits2/audits2Dialog.css",
"front_end/audits2/audits2StartView.css", "front_end/audits2/audits2StartView.css",
"front_end/audits2/audits2Panel.css", "front_end/audits2/audits2Panel.css",
"front_end/audits2/RadioSetting.js",
"front_end/audits2/lighthouse/renderer/dom.js", "front_end/audits2/lighthouse/renderer/dom.js",
"front_end/audits2/lighthouse/renderer/details-renderer.js", "front_end/audits2/lighthouse/renderer/details-renderer.js",
"front_end/audits2/lighthouse/renderer/category-renderer.js", "front_end/audits2/lighthouse/renderer/category-renderer.js",
......
...@@ -198,7 +198,7 @@ Audits2.AuditController = class extends Common.Object { ...@@ -198,7 +198,7 @@ Audits2.AuditController = class extends Common.Object {
}; };
/** @typedef {{type: string, setting: !Common.Setting, configID: string, title: string, description: string}} */ /** @typedef {{setting: !Common.Setting, configID: string, title: string, description: string}} */
Audits2.Preset; Audits2.Preset;
/** @type {!Array.<!Audits2.Preset>} */ /** @type {!Array.<!Audits2.Preset>} */
...@@ -236,44 +236,41 @@ Audits2.Presets = [ ...@@ -236,44 +236,41 @@ Audits2.Presets = [
}, },
]; ];
/** @typedef {{setting: !Common.Setting, description: string, setFlags: function(!Object, string), options: !Array}} */ /** @typedef {{setting: !Common.Setting, description: string, setFlags: function(!Object, string), options: (!Array|undefined), title: (string|undefined)}} */
Audits2.RuntimeSetting; Audits2.RuntimeSetting;
/** @type {!Array.<!Audits2.RuntimeSetting>} */ /** @type {!Array.<!Audits2.RuntimeSetting>} */
Audits2.RuntimeSettings = [ Audits2.RuntimeSettings = [
{ {
setting: Common.settings.createSetting('audits2.device_type', 'mobile'), setting: Common.settings.createSetting('audits2.device_type', 'mobile'),
description: Common.UIString('Apply mobile emulation during auditing'), description: ls`Apply mobile emulation during auditing`,
setFlags: (flags, value) => { setFlags: (flags, value) => {
flags.disableDeviceEmulation = value === 'desktop'; flags.disableDeviceEmulation = value === 'desktop';
}, },
options: [ options: [
{label: Common.UIString('Mobile'), value: 'mobile'}, {label: ls`Mobile`, value: 'mobile'},
{label: Common.UIString('Desktop'), value: 'desktop'}, {label: ls`Desktop`, value: 'desktop'},
], ],
}, },
{ {
setting: Common.settings.createSetting('audits2.throttling', 'default'), setting: Common.settings.createSetting('audits2.throttling', 'default'),
description: Common.UIString('Apply network and CPU throttling during performance auditing'), description: ls`Apply network and CPU throttling during performance auditing`,
setFlags: (flags, value) => { setFlags: (flags, value) => {
flags.disableNetworkThrottling = value === 'off'; flags.disableNetworkThrottling = value === 'off';
flags.disableCpuThrottling = value === 'off'; flags.disableCpuThrottling = value === 'off';
}, },
options: [ options: [
{label: Common.UIString('3G w/ CPU slowdown'), value: 'default'}, {label: ls`Fast 3G with 4x CPU Slowdown`, value: 'default'},
{label: Common.UIString('No throttling'), value: 'off'}, {label: ls`No throttling`, value: 'off'},
], ],
}, },
{ {
setting: Common.settings.createSetting('audits2.storage_reset', 'on'), setting: Common.settings.createSetting('audits2.clear_storage', true),
description: Common.UIString('Reset storage (localStorage, IndexedDB, etc) to a clean baseline before auditing'), title: ls`Clear storage`,
description: ls`Reset storage (localStorage, IndexedDB, etc) to a clean baseline before auditing`,
setFlags: (flags, value) => { setFlags: (flags, value) => {
flags.disableStorageReset = value === 'off'; flags.disableStorageReset = !value;
}, },
options: [
{label: Common.UIString('Clear storage'), value: 'on'},
{label: Common.UIString('Preserve storage'), value: 'off'},
],
}, },
]; ];
......
...@@ -29,6 +29,7 @@ Audits2.Audits2Panel = class extends UI.Panel { ...@@ -29,6 +29,7 @@ Audits2.Audits2Panel = class extends UI.Panel {
this._controller.addEventListener(Audits2.Events.RequestAuditCancel, this._cancelAudit.bind(this)); this._controller.addEventListener(Audits2.Events.RequestAuditCancel, this._cancelAudit.bind(this));
this._renderToolbar(); this._renderToolbar();
this.contentElement.createChild('div', 'audits2-dialog-overlay');
this._auditResultsElement = this.contentElement.createChild('div', 'audits2-results-container'); this._auditResultsElement = this.contentElement.createChild('div', 'audits2-results-container');
this._renderStartView(); this._renderStartView();
...@@ -99,7 +100,9 @@ Audits2.Audits2Panel = class extends UI.Panel { ...@@ -99,7 +100,9 @@ Audits2.Audits2Panel = class extends UI.Panel {
this._startView.show(this.contentElement); this._startView.show(this.contentElement);
this._startView.setUnauditableExplanation(this._unauditableExplanation); this._startView.setUnauditableExplanation(this._unauditableExplanation);
this._startView.setStartButtonEnabled(!this._unauditableExplanation); this._startView.setStartButtonEnabled(!this._unauditableExplanation);
this._newButton.setEnabled(false);
this._refreshToolbarUI(); this._refreshToolbarUI();
this.setDefaultFocusedChild(this._startView);
} }
/** /**
...@@ -119,6 +122,7 @@ Audits2.Audits2Panel = class extends UI.Panel { ...@@ -119,6 +122,7 @@ Audits2.Audits2Panel = class extends UI.Panel {
this._startView.hideWidget(); this._startView.hideWidget();
this._statusView.hide(); this._statusView.hide();
this._auditResultsElement.removeChildren(); this._auditResultsElement.removeChildren();
this._newButton.setEnabled(true);
this._refreshToolbarUI(); this._refreshToolbarUI();
const cachedRenderedReport = this._cachedRenderedReports.get(lighthouseResult); const cachedRenderedReport = this._cachedRenderedReports.get(lighthouseResult);
......
...@@ -20,20 +20,37 @@ Audits2.StartView = class extends UI.Widget { ...@@ -20,20 +20,37 @@ Audits2.StartView = class extends UI.Widget {
* @param {string} settingName * @param {string} settingName
* @param {!Element} parentElement * @param {!Element} parentElement
*/ */
_populateRuntimeSettingAsComboBox(settingName, parentElement) { _populateRuntimeSettingAsRadio(settingName, parentElement) {
const runtimeSetting = Audits2.RuntimeSettings.find(item => item.setting.name === settingName); const runtimeSetting = Audits2.RuntimeSettings.find(item => item.setting.name === settingName);
const control = new UI.ToolbarSettingComboBox(runtimeSetting.options, runtimeSetting.setting); if (!runtimeSetting || !runtimeSetting.options)
throw new Error(`${settingName} is not a setting with options`);
const control = new Audits2.RadioSetting(runtimeSetting.options, runtimeSetting.setting);
control.element.title = runtimeSetting.description; control.element.title = runtimeSetting.description;
parentElement.appendChild(control.element); parentElement.appendChild(control.element);
} }
/**
* @param {string} settingName
* @param {!Element} parentElement
*/
_populateRuntimeSettingAsCheckbox(settingName, parentElement) {
const runtimeSetting = Audits2.RuntimeSettings.find(item => item.setting.name === settingName);
if (!runtimeSetting || !runtimeSetting.title)
throw new Error(`${settingName} is not a setting with a title`);
runtimeSetting.setting.setTitle(runtimeSetting.title);
const control = new UI.ToolbarSettingCheckbox(runtimeSetting.setting, runtimeSetting.description);
parentElement.appendChild(control.element);
}
/** /**
* @param {!UI.Fragment} fragment * @param {!UI.Fragment} fragment
*/ */
_populateFormControls(fragment) { _populateFormControls(fragment) {
// Populate the device type // Populate the device type
const deviceTypeFormElements = fragment.$('device-type-form-elements'); const deviceTypeFormElements = fragment.$('device-type-form-elements');
this._populateRuntimeSettingAsComboBox('audits2.device_type', deviceTypeFormElements); this._populateRuntimeSettingAsRadio('audits2.device_type', deviceTypeFormElements);
// Populate the audit categories // Populate the audit categories
const categoryFormElements = fragment.$('categories-form-elements'); const categoryFormElements = fragment.$('categories-form-elements');
...@@ -41,38 +58,39 @@ Audits2.StartView = class extends UI.Widget { ...@@ -41,38 +58,39 @@ Audits2.StartView = class extends UI.Widget {
preset.setting.setTitle(preset.title); preset.setting.setTitle(preset.title);
const checkbox = new UI.ToolbarSettingCheckbox(preset.setting); const checkbox = new UI.ToolbarSettingCheckbox(preset.setting);
const row = categoryFormElements.createChild('div', 'vbox audits2-launcher-row'); const row = categoryFormElements.createChild('div', 'vbox audits2-launcher-row');
row.title = preset.description;
row.appendChild(checkbox.element); row.appendChild(checkbox.element);
row.createChild('span', 'audits2-launcher-description dimmed').textContent = preset.description;
} }
// Populate the throttling // Populate the throttling
const throttlingFormElements = fragment.$('throttling-form-elements'); const throttlingFormElements = fragment.$('throttling-form-elements');
this._populateRuntimeSettingAsComboBox('audits2.throttling', throttlingFormElements); this._populateRuntimeSettingAsRadio('audits2.throttling', throttlingFormElements);
// Populate other settings // Populate other settings
const otherFormElements = fragment.$('other-form-elements'); const otherFormElements = fragment.$('other-form-elements');
this._populateRuntimeSettingAsComboBox('audits2.storage_reset', otherFormElements); this._populateRuntimeSettingAsCheckbox('audits2.clear_storage', otherFormElements);
} }
_render() { _render() {
this._startButton = UI.createTextButton( this._startButton = UI.createTextButton(
ls`Run audit`, () => this._controller.dispatchEventToListeners(Audits2.Events.RequestAuditStart), ls`Run audits`, () => this._controller.dispatchEventToListeners(Audits2.Events.RequestAuditStart),
'audits2-start-button', true /* primary */); 'audits2-start-button', true /* primary */);
this.setDefaultFocusedElement(this._startButton);
const deviceIcon = UI.Icon.create('largeicon-phone'); const deviceIcon = UI.Icon.create('largeicon-phone');
const categoriesIcon = UI.Icon.create('largeicon-checkmark'); const categoriesIcon = UI.Icon.create('largeicon-checkmark');
const throttlingIcon = UI.Icon.create('largeicon-settings-gear'); const throttlingIcon = UI.Icon.create('largeicon-settings-gear');
const fragment = UI.Fragment.build` const fragment = UI.Fragment.build`
<div class="vbox audits2-start-view"> <div class="vbox audits2-start-view">
<div class="audits2-dialog-overlay"></div>
<header> <header>
<div class="audits2-logo"></div> <div class="audits2-logo"></div>
<div class="audits2-start-view-text"> <div class="audits2-start-view-text">
<h2>Audits</h2> <h2>Audits</h2>
<p> <p>
Identify and fix common problems that affect your site's performance, accessibility, and user experience. Identify and fix common problems that affect your site's performance, accessibility, and user experience.
<span class="link" $="learn-more">Learn more.</a> <span class="link" $="learn-more">Learn more</a>
</p> </p>
</div> </div>
</header> </header>
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
Audits2.RadioSetting = class {
/**
* @param {!Array<!{value: string, label: string}>} options
* @param {!Common.Setting} setting
*/
constructor(options, setting) {
this._setting = setting;
this._options = options;
this.element = createElement('div', 'audits2-radio-group');
this._radioElements = [];
for (const option of this._options) {
const fragment = UI.Fragment.build`
<label class="audits2-radio">
<input $="input" type="radio" value=${option.value} name=${setting.name}>
${option.label}
</label>
`;
this.element.appendChild(fragment.element());
const radioElement = fragment.$('input');
radioElement.addEventListener('change', this._valueChanged.bind(this));
this._radioElements.push(radioElement);
}
this._ignoreChangeEvents = false;
this._selectedIndex = -1;
setting.addChangeListener(this._settingChanged, this);
this._settingChanged();
}
_updateUI() {
this._ignoreChangeEvents = true;
this._radioElements[this._selectedIndex].checked = true;
this._ignoreChangeEvents = false;
}
_settingChanged() {
const value = this._setting.get();
this._selectedIndex = this._options.findIndex(option => option.value === value);
this._updateUI();
}
/**
* @param {!Event} event
*/
_valueChanged(event) {
if (this._ignoreChangeEvents)
return;
const selectedRadio = this._radioElements.find(radio => radio.checked);
this._setting.set(selectedRadio.value);
}
};
\ No newline at end of file
...@@ -31,7 +31,8 @@ ...@@ -31,7 +31,8 @@
.audits2-status-text { .audits2-status-text {
text-align: center; text-align: center;
height: 60px; min-height: 50px;
margin-bottom: 10px;
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
......
...@@ -6,10 +6,12 @@ ...@@ -6,10 +6,12 @@
.audits2-start-view { .audits2-start-view {
font-family: Roboto, sans-serif; font-family: Roboto, sans-serif;
font-size: 13px;
line-height: 18px;
} }
.audits2-dialog-overlay { .audits2-dialog-overlay {
position: fixed; position: absolute;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: none; display: none;
...@@ -22,7 +24,7 @@ ...@@ -22,7 +24,7 @@
} }
.audits2-start-view header { .audits2-start-view header {
padding: 10px; padding: 0 16px;
display: flex; display: flex;
} }
...@@ -32,7 +34,7 @@ ...@@ -32,7 +34,7 @@
flex-shrink: 0; flex-shrink: 0;
background-repeat: no-repeat; background-repeat: no-repeat;
background-size: contain; background-size: contain;
margin-right: 18px; margin-right: 20px;
background-image: url(Images/audits_logo.svg); background-image: url(Images/audits_logo.svg);
} }
...@@ -44,42 +46,61 @@ ...@@ -44,42 +46,61 @@
.audits2-start-view-text h2 { .audits2-start-view-text h2 {
color: black; color: black;
font-weight: normal; font-weight: normal;
font-size: 18px;
margin-bottom: 12px;
}
.audits2-start-view-text p {
margin-top: 0;
}
.audits2-start-view form {
padding: 0 16px;
} }
.audits2-form-section { .audits2-form-section {
border-top: 1px solid #e8e8e8; border-top: 1px solid #ebebeb;
display: flex; display: flex;
padding: 20px; padding: 16px 8px;
}
.audits2-form-section:last-child {
border-top: none;
padding-top: 0;
} }
.audits2-form-section-label { .audits2-form-section-label {
flex: 1;
display: flex; display: flex;
width: 160px;
} }
.audits2-form-section-label i { .audits2-form-section-label i {
width: 30px; width: 16px;
height: 30px; height: 16px;
border-radius: 50%;
background: #e6e6e6;
display: block; display: block;
text-align: center; text-align: center;
padding-top: 3px;
} }
.audits2-icon-label { .audits2-icon-label {
margin: 7px; margin: 0 14px;
font-size: 1.2em;
} }
.audits2-form-section-label span.largeicon-checkmark { .audits2-form-section-label i span {
transform: scale(1.3);
position: relative; position: relative;
right: -2px; top: -2px;
}
.audits2-form-section-label span.largeicon-checkmark {
top: -4px;
}
.audits2-radio {
display: block;
margin-bottom: 8px;
} }
.audits2-form-elements { .audits2-radio:last-child {
flex: 3; margin-bottom: 0;
} }
.audits2-start-button-container { .audits2-start-button-container {
...@@ -95,7 +116,7 @@ ...@@ -95,7 +116,7 @@
} }
.audits2-launcher-row { .audits2-launcher-row {
padding-bottom: 10px; padding-bottom: 8px;
} }
.audits2-launcher-row:last-of-type { .audits2-launcher-row:last-of-type {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
"lighthouse/renderer/details-renderer.js", "lighthouse/renderer/details-renderer.js",
"lighthouse/renderer/crc-details-renderer.js", "lighthouse/renderer/crc-details-renderer.js",
"lighthouse/renderer/report-renderer.js", "lighthouse/renderer/report-renderer.js",
"RadioSetting.js",
"Audits2Panel.js", "Audits2Panel.js",
"Audits2Controller.js", "Audits2Controller.js",
"Audits2ReportSelector.js", "Audits2ReportSelector.js",
......
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