diff --git a/lighthouse-core/report/v2/renderer/category-renderer.js b/lighthouse-core/report/v2/renderer/category-renderer.js index eeb0adef8cc6..b61b8b1933b3 100644 --- a/lighthouse-core/report/v2/renderer/category-renderer.js +++ b/lighthouse-core/report/v2/renderer/category-renderer.js @@ -117,16 +117,18 @@ class CategoryRenderer { * @return {!Element} */ _renderTimelineMetricAudit(audit, scale) { - const element = this._dom.createElement('div', - `lh-timeline-metric lh-timeline-metric--${Util.calculateRating(audit.score)}`); + const tmpl = this._dom.cloneTemplate('#tmpl-lh-timeline-metric', this._templateContext); + const element = this._dom.find('.lh-timeline-metric', tmpl); + element.classList.add(`lh-timeline-metric--${Util.calculateRating(audit.score)}`); - const sparklineContainerEl = this._dom.createChildOf(element, 'div', - 'lh-timeline-metric__sparkline'); - const titleEl = this._dom.createChildOf(element, 'div', 'lh-timeline-metric__title'); - const titleNameEl = this._dom.createChildOf(titleEl, 'span', 'lh-timeline-metric__name'); - const titleValueEl = this._dom.createChildOf(titleEl, 'span', 'lh-timeline-metric__value'); - titleNameEl.textContent = audit.result.description; - titleValueEl.textContent = audit.result.displayValue; + const titleEl = this._dom.find('.lh-timeline-metric__title', tmpl); + titleEl.textContent = audit.result.description; + + const valueEl = this._dom.find('.lh-timeline-metric__value', tmpl); + valueEl.textContent = audit.result.displayValue; + + const descriptionEl = this._dom.find('.lh-timeline-metric__description', tmpl); + descriptionEl.appendChild(this._dom.convertMarkdownLinkSnippets(audit.result.helpText)); if (typeof audit.result.rawValue !== 'number') { const debugStrEl = this._dom.createChildOf(element, 'div', 'lh-debug'); @@ -134,15 +136,9 @@ class CategoryRenderer { return element; } - const sparklineEl = this._dom.createChildOf(sparklineContainerEl, 'div', - 'lh-sparkline lh-sparkline--thin'); - const sparklineBarEl = this._dom.createChildOf(sparklineEl, 'div', 'lh-sparkline__bar'); + const sparklineBarEl = this._dom.find('.lh-sparkline__bar', tmpl); sparklineBarEl.style.width = `${audit.result.rawValue / scale * 100}%`; - const descriptionEl = this._dom.createChildOf(element, 'div', - 'lh-timeline-metric__description'); - descriptionEl.appendChild(this._dom.convertMarkdownLinkSnippets(audit.result.helpText)); - return element; } @@ -219,9 +215,6 @@ class CategoryRenderer { 'lh-audit-group__header lh-expandable-details__header'); auditGroupHeader.textContent = group.title; - const auditGroupDescription = this._dom.createElement('div', 'lh-audit-group__description'); - auditGroupDescription.appendChild(this._dom.convertMarkdownLinkSnippets(group.description)); - const auditGroupSummary = this._dom.createElement('summary', 'lh-audit-group__summary lh-expandable-details__summary'); const auditGroupArrow = this._dom.createElement('div', 'lh-toggle-arrow', { @@ -229,9 +222,14 @@ class CategoryRenderer { }); auditGroupSummary.appendChild(auditGroupHeader); auditGroupSummary.appendChild(auditGroupArrow); - auditGroupElem.appendChild(auditGroupSummary); - auditGroupElem.appendChild(auditGroupDescription); + + if (group.description) { + const auditGroupDescription = this._dom.createElement('div', 'lh-audit-group__description'); + auditGroupDescription.appendChild(this._dom.convertMarkdownLinkSnippets(group.description)); + auditGroupElem.appendChild(auditGroupDescription); + } + return auditGroupElem; } @@ -240,10 +238,10 @@ class CategoryRenderer { * @return {!Element} */ _renderPassedAuditsSection(elements) { - const passedElem = this._dom.createElement('details', 'lh-passed-audits'); - const passedSummary = this._dom.createElement('summary', 'lh-passed-audits-summary'); - passedElem.appendChild(passedSummary); - passedSummary.textContent = `View ${elements.length} passed items`; + const passedElem = this._renderAuditGroup({ + title: `${elements.length} Passed Audits`, + }); + passedElem.classList.add('lh-passed-audits'); elements.forEach(elem => passedElem.appendChild(elem)); return passedElem; } @@ -344,14 +342,18 @@ class CategoryRenderer { !audit.result.debugString); const nonPassedAudits = nonManualAudits.filter(audit => !passedAudits.includes(audit)); - for (const audit of nonPassedAudits) { - element.appendChild(this._renderAudit(audit)); - } + const nonPassedElem = this._renderAuditGroup({ + title: `${nonPassedAudits.length} failed audits`, + }); + nonPassedElem.open = true; + nonPassedAudits.forEach(audit => nonPassedElem.appendChild(this._renderAudit(audit))); + element.appendChild(nonPassedElem); // Create a passed section if there are passing audits. if (passedAudits.length) { - const passedElements = passedAudits.map(audit => this._renderAudit(audit)); - const passedElem = this._renderPassedAuditsSection(passedElements); + const passedElem = this._renderPassedAuditsSection( + passedAudits.map(audit => this._renderAudit(audit)) + ); element.appendChild(passedElem); } diff --git a/lighthouse-core/report/v2/renderer/report-renderer.js b/lighthouse-core/report/v2/renderer/report-renderer.js index 4270da331e35..20075372f61b 100644 --- a/lighthouse-core/report/v2/renderer/report-renderer.js +++ b/lighthouse-core/report/v2/renderer/report-renderer.js @@ -198,7 +198,7 @@ ReportRenderer.CategoryJSON; // eslint-disable-line no-unused-expressions /** * @typedef {{ * title: string, - * description: string, + * description: (string|undefined), * }} */ ReportRenderer.GroupJSON; // eslint-disable-line no-unused-expressions diff --git a/lighthouse-core/report/v2/report-styles.css b/lighthouse-core/report/v2/report-styles.css index b971949c090c..bc6875a1325e 100644 --- a/lighthouse-core/report/v2/report-styles.css +++ b/lighthouse-core/report/v2/report-styles.css @@ -5,14 +5,24 @@ */ .lh-vars { - --text-font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif; + --text-font-family: Roboto, Helvetica, Arial, sans-serif; --monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; - --body-font-size: 12px; - --header-font-size: 14px; - --body-line-height: 1.5; + --body-font-size: 14px; + --body-line-height: 18px; + --subheader-font-size: 16px; + --subheader-line-height: 20px; + --header-font-size: 20px; + --header-line-height: 24px; + --title-font-size: 24px; + --title-line-height: 28px; + --caption-font-size: 12px; + --caption-line-height: 16px; --default-padding: 12px; - --section-padding: 16px; - + --section-padding: 20px; + --section-indent: 16px; + --audit-group-indent: 16px; + --audit-indent: 16px; + --expandable-indent: 20px; --secondary-text-color: #565656; /*--accent-color: #3879d9;*/ --fail-color: #df332f; @@ -21,25 +31,59 @@ --manual-color: #757575; --average-color: #ef6c00; /* md orange 800 */ --warning-color: #ffab00; /* md amber a700 */ - --report-border-color: #ccc; --report-secondary-border-color: #ebebeb; - --report-width: 850px; - --report-menu-width: 280px; + --report-width: calc(60 * var(--body-font-size)); + --report-menu-width: calc(20 * var(--body-font-size)); --report-content-width: calc(var(--report-width) + var(--report-menu-width)); - + --navitem-font-size: var(--body-font-size); + --navitem-line-height: var(--body-line-height); + --navitem-hpadding: var(--body-font-size); + --navitem-vpadding: calc(var(--navitem-line-height) / 2); --lh-score-highlight-bg: #fafafa; --lh-score-icon-background-size: 24px; - --lh-score-margin: calc(var(--default-padding) / 2); - + --lh-score-margin: 12px; --lh-table-header-bg: #ccc; --lh-table-higlight-bg: #fafafa; - --lh-sparkline-height: 8px; --lh-sparkline-thin-height: 3px; --lh-filmstrip-thumbnail-width: 60px; - --lh-audit-score-width: 35px; - --lh-category-score-width: 60px; + --lh-audit-score-width: calc(5 * var(--body-font-size)); + --lh-category-score-width: calc(5 * var(--body-font-size)); + --lh-audit-vpadding: 8px; + --lh-audit-hgap: 12px; + --lh-audit-group-vpadding: 12px; + --lh-section-vpadding: 12px; + --pass-icon-url: url('data:image/svg+xml;utf8,'); + --fail-icon-url: url('data:image/svg+xml;utf8,'); + --collapsed-icon-url: url('data:image/svg+xml;utf8,'); + --expanded-icon-url: url('data:image/svg+xml;utf8,'); +} + +.lh-vars.lh-devtools { + --text-font-family: '.SFNSDisplay-Regular', 'Helvetica Neue', 'Lucida Grande', sans-serif; + --monospace-font-family: 'Menlo', 'dejavu sans mono', 'Consolas', 'Lucida Console', monospace; + --body-font-size: 12px; + --body-line-height: 16px; + --subheader-font-size: 14px; + --subheader-line-height: 18px; + --header-font-size: 16px; + --header-line-height: 20px; + --title-font-size: 20px; + --title-line-height: 24px; + --caption-font-size: 10px; + --caption-line-height: 14px; + --default-padding: 12px; + --section-padding: 16px; + --section-indent: 16px; + --audit-group-indent: 16px; + --audit-indent: 16px; + --expandable-indent: 16px; + + --lh-audit-vpadding: 4px; + --lh-audit-hgap: 12px; + --lh-audit-group-vpadding: 8px; + --lh-section-vpadding: 8px; } .lh-root * { @@ -181,25 +225,22 @@ span.lh-node:hover { .lh-score__value { flex: none; - margin-right: var(--lh-score-margin); + margin-left: var(--lh-score-margin); width: var(--lh-audit-score-width); - display: flex; - justify-content: center; - align-items: center; - border-radius: 2px; position: relative; font-weight: bold; top: 1px; + text-align: right; } .lh-score__value::after { content: ''; position: absolute; - left: 0; right: 0; top: 0; bottom: 0; border-radius: inherit; + width: 16px; } .lh-score--informative .lh-score__value { @@ -209,6 +250,7 @@ span.lh-node:hover { } .lh-score--informative .lh-score__value::after { + display: none; background: url('data:image/svg+xml;utf8,info') no-repeat 50% 50%; background-size: var(--lh-score-icon-background-size); } @@ -223,7 +265,7 @@ span.lh-node:hover { } .lh-score__value--binary { - text-indent: -5000px; + color: transparent !important; } /* No icon for audits with number scores. */ @@ -236,8 +278,7 @@ span.lh-node:hover { } .lh-score__value--pass::after { - background: url('data:image/svg+xml;utf8,pass') no-repeat 50% 50%; - background-size: var(--lh-score-icon-background-size); + background: var(--pass-icon-url) no-repeat center center / 12px 12px; } .lh-score__value--average { @@ -260,14 +301,13 @@ span.lh-node:hover { } .lh-score__value--fail::after { - background: url('data:image/svg+xml;utf8,fail') no-repeat 50% 50%; - background-size: var(--lh-score-icon-background-size); + background: var(--fail-icon-url) no-repeat center center / 12px 12px; } .lh-score__description { - font-size: smaller; + font-size: var(--body-font-size); color: var(--secondary-text-color); - margin-top: calc(var(--default-padding) / 2); + line-height: var(--body-line-height); } .lh-score__snippet { @@ -280,29 +320,45 @@ span.lh-node:hover { display: none; } +.lh-score__title { + flex: 1; +} + .lh-toggle-arrow { - background: url('data:image/svg+xml;utf8,') no-repeat 50% 50%; - background-size: contain; + background: var(--collapsed-icon-url) no-repeat center center / 12px 12px; background-color: transparent; - width: 24px; - height: 24px; + width: 12px; + height: 12px; flex: none; - margin-left: calc(var(--default-padding) / 2); transition: transform 150ms ease-in-out; cursor: pointer; border: none; - transform: rotateZ(90deg); + order: -1; + margin-right: calc(var(--expandable-indent) - 12px); + align-self: flex-start; } /* Expandable Details (Audit Groups, Audits) */ .lh-expandable-details { flex: 1; + padding-left: var(--expandable-indent); +} + +.lh-score__header { + order: -1; + flex: 1; } .lh-expandable-details__summary { display: flex; cursor: pointer; + align-items: center; + margin-left: calc(0px - var(--expandable-indent)); +} + +.lh-expandable-details__summary:focus { + outline: 0; } .lh-expandable-details__header { @@ -310,7 +366,7 @@ span.lh-node:hover { } .lh-expandable-details[open] > .lh-expandable-details__summary > .lh-toggle-arrow { - transform: rotateZ(-90deg); + background-image: var(--expanded-icon-url); } .lh-expandable-details__summary::-webkit-details-marker { @@ -321,10 +377,14 @@ span.lh-node:hover { outline: rgb(59, 153, 252) auto 5px; }*/ +.lh-score__snippet .lh-toggle-arrow { + margin-top: calc((var(--body-line-height) - 12px) / 2); +} + /* Perf Timeline */ .lh-timeline { - padding: var(--default-padding); + padding: 0; padding-bottom: 0; min-width: calc(var(--lh-filmstrip-thumbnail-width) * 10 + var(--default-padding) * 2); } @@ -342,21 +402,37 @@ span.lh-node:hover { /* Perf Timeline Metric */ .lh-timeline-metric { - padding: 5px 0; - margin-bottom: calc(var(--body-font-size) / 2); + position: relative; + margin-bottom: calc(2 * var(--lh-audit-vpadding)); + padding-top: var(--lh-audit-vpadding); + border-top: 1px solid var(--report-secondary-border-color); +} + +.lh-timeline-metric__header { + display: flex; +} + +.lh-timeline-metric__details { + order: -1; } .lh-timeline-metric__title { - font-size: var(--header-font-size); + font-size: var(--body-font-size); + line-height: var(--body-line-height); + display: flex; +} + +.lh-timeline-metric__name { + flex: 1; } .lh-timeline-metric__description { color: var(--secondary-text-color); } -.lh-timeline-metric__name::after { - margin-right: 10px; - content: ':'; +.lh-timeline-metric__value { + width: var(--lh-audit-score-width); + text-align: right; } .lh-timeline-metric--pass .lh-timeline-metric__value { @@ -372,15 +448,14 @@ span.lh-node:hover { } .lh-timeline-metric__sparkline { + position: absolute; + left: 0; + right: 0; + top: -1px; + height: 3px; width: 100%; } -.lh-timeline-metric__sparkline .lh-sparkline { - margin-left: 0; - margin-right: 0; - border-bottom: 1px solid var(--report-border-color); -} - .lh-timeline-metric__sparkline .lh-sparkline__bar { float: none; } @@ -397,13 +472,16 @@ span.lh-node:hover { background: var(--fail-color); } +.lh-timeline-metric .lh-debug { + margin-left: var(--expandable-indent); +} + /* Perf Hint */ .lh-perf-hint { - margin-top: var(--default-padding); - margin-left: var(--default-padding); - padding-bottom: var(--default-padding); - border-bottom: 1px solid var(--report-secondary-border-color); + padding-top: var(--lh-audit-vpadding); + padding-bottom: var(--lh-audit-vpadding); + border-top: 1px solid var(--report-secondary-border-color); } .lh-perf-hint:last-of-type { @@ -412,30 +490,43 @@ span.lh-node:hover { .lh-perf-hint__summary { display: flex; - align-items: center; + align-items: flex-start; + min-height: calc(var(--body-line-height) + var(--caption-line-height)); +} + +.lh-perf-hint__summary .lh-toggle-arrow { + margin-top: calc((var(--subheader-line-height) - 12px) / 2); } .lh-perf-hint__title { - font-size: var(--header-font-size); + font-size: var(--body-font-size); flex: 10; } .lh-perf-hint__sparkline { flex: 0 0 50%; + margin-top: calc((var(--body-line-height) - var(--lh-sparkline-height)) / 2); } .lh-perf-hint__sparkline .lh-sparkline { - width: calc(100% - var(--default-padding) * 2); + width: 100%; float: right; + margin: 0; } .lh-perf-hint__stats { text-align: right; - flex: 0 0 70px; + flex: 0 0 var(--lh-audit-score-width); } .lh-perf-hint__primary-stat { - font-size: var(--header-font-size); + font-size: var(--body-font-size); + line-height: var(--body-line-height); +} + +.lh-perf-hint__secondary-stat { + font-size: var(--caption-font-size); + line-height: var(--caption-line-height); } .lh-perf-hint__description { @@ -481,7 +572,9 @@ span.lh-node:hover { } .lh-filmstrip__timestamp { - margin-bottom: 5px; + margin-bottom: calc(0.5 * var(--caption-line-height)); + font-size: var(--caption-font-size); + line-height: var(--caption-line-height); } .lh-filmstrip__thumbnail { @@ -510,9 +603,9 @@ span.lh-node:hover { /* Audit */ .lh-audit { - margin-top: var(--default-padding); - padding-bottom: var(--default-padding); - border-bottom: 1px solid var(--report-secondary-border-color); + margin-bottom: var(--lh-audit-vpadding); + padding-top: var(--lh-audit-vpadding); + border-top: 1px solid var(--report-secondary-border-color); } .lh-audit:last-of-type { @@ -520,15 +613,20 @@ span.lh-node:hover { } .lh-audit > .lh-score { - font-size: var(--header-font-size); + font-size: var(--body-font-size); +} + +.lh-audit .lh-debug { + margin-left: var(--expandable-indent); + margin-right: var(--lh-audit-score-width); } /* Audit Group */ .lh-audit-group { - padding-top: var(--default-padding); - padding-bottom: var(--default-padding); + padding-top: var(--lh-audit-group-vpadding); border-top: 1px solid var(--report-secondary-border-color); + padding-left: var(--expandable-indent); } .lh-category > .lh-audit-group.lh-audit-group--manual { @@ -537,7 +635,8 @@ span.lh-node:hover { } .lh-audit-group__header { - font-size: 18px; + font-size: var(--subheader-font-size); + line-height: var(--subheader-line-height); } .lh-audit-group--manual .lh-audit-group__summary { @@ -559,20 +658,31 @@ span.lh-node:hover { background: var(--manual-color) !important; } +.lh-audit-group__summary { + margin-bottom: var(--lh-audit-group-vpadding); +} + +.lh-audit-group__summary .lh-toggle-arrow { + margin-top: calc((var(--subheader-line-height) - 12px) / 2); +} + .lh-audit-group__description { - font-size: var(--header-font-size); + font-size: var(--body-font-size); color: var(--secondary-text-color); - margin-top: calc(var(--default-padding) / 2); + margin-top: calc(0px - var(--lh-audit-group-vpadding)); + margin-bottom: var(--lh-audit-group-vpadding); + line-height: var(--body-line-height); } + .lh-debug { - margin-top: calc(var(--default-padding) / 2); - margin-left: calc(var(--lh-audit-score-width) + var(--lh-score-margin)); + font-size: var(--caption-font-size); + line-height: var(--caption-line-height); color: var(--fail-color); } .lh-debug::before { - display: inline-block; + display: none; content: ''; background: url('data:image/svg+xml;utf8,warn') no-repeat 50% 50%; background-size: contain; @@ -594,7 +704,6 @@ span.lh-node:hover { .lh-report { margin-left: var(--report-menu-width); - width: var(--report-width); background-color: #fff; padding-top: var(--report-header-height); } @@ -615,9 +724,9 @@ span.lh-node:hover { .lh-scores-header { display: flex; + justify-content: center; overflow-x: hidden; - margin: var(--report-header-height) 0 0 0; - padding: calc(var(--default-padding) * 2) var(--default-padding); + padding: var(--section-padding); border-bottom: 1px solid var(--report-border-color); } .lh-scores-header__solo { @@ -639,25 +748,9 @@ span.lh-node:hover { border: none; } -.lh-category .lh-audit { - margin-left: calc(var(--default-padding) * 2); -} - -.lh-category .lh-audit-group { - margin-left: calc(var(--lh-category-score-width) + var(--default-padding)); -} - -.lh-category > .lh-audit-group { - margin-left: 0; -} - -.lh-category .lh-audit-group .lh-audit { - margin-left: var(--default-padding); -} - .lh-category > .lh-score { - font-size: 20px; - padding-bottom: var(--default-padding); + font-size: var(--header-font-size); + padding-bottom: var(--lh-section-vpadding); } .lh-category > .lh-score .lh-score__value, @@ -666,13 +759,13 @@ span.lh-node:hover { } .lh-category .lh-score__gauge { - margin: calc(var(--default-padding) / 2) var(--default-padding) 0 0; + margin-left: var(--section-indent); flex-basis: var(--circle-size); flex-shrink: 0; } .lh-category .lh-score__gauge .lh-gauge { - --circle-size: 60px; + --circle-size: calc(2.5 * var(--header-font-size)); } /* Category snippet shouldnt have pointer cursor. */ @@ -681,8 +774,8 @@ span.lh-node:hover { } .lh-category > .lh-score .lh-score__title { - font-size: 24px; - font-weight: 400; + font-size: var(--header-font-size); + line-height: var(--header-line-height); } .lh-passed-audits[open] summary.lh-passed-audits-summary { @@ -737,14 +830,19 @@ summary.lh-passed-audits-summary::-webkit-details-marker, transform: translateY(0); } -@media screen and (max-width: 767px) { +@media screen and (min-width: 960px) { + .lh-report { + width: var(--report-width); + } +} + +@media screen and (max-width: 720px) { .lh-report { margin-left: 0; width: 100%; min-width: 400px; } .lh-category { - padding: 24px var(--default-padding); } } diff --git a/lighthouse-core/report/v2/templates.html b/lighthouse-core/report/v2/templates.html index 7428e17ce025..996b3e93659f 100644 --- a/lighthouse-core/report/v2/templates.html +++ b/lighthouse-core/report/v2/templates.html @@ -26,12 +26,31 @@ + + +