Skip to content

Commit

Permalink
report: add explodey gauge for performance category (#15396)
Browse files Browse the repository at this point in the history
  • Loading branch information
connorjclark committed Oct 2, 2023
1 parent a11b417 commit 6a4c751
Show file tree
Hide file tree
Showing 8 changed files with 680 additions and 8 deletions.
226 changes: 226 additions & 0 deletions report/assets/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -1964,5 +1964,231 @@ details[open] .lh-clump-toggletext--hide { display: block;}
}
}

/* Explodey gauge */

.lh-exp-gauge-component {
margin-bottom: 10px;
}

.lh-exp-gauge-component circle {
stroke: currentcolor;
r: var(--radius);
}

.lh-exp-gauge-component text {
font-size: calc(var(--radius) * 0.2);
}

.lh-exp-gauge-component .lh-exp-gauge {
margin: 0 auto;
width: 225px;
stroke-width: var(--stroke-width);
stroke-linecap: round;

/* for better rendering perf */
contain: strict;
height: 225px;
will-change: transform;
}
.lh-exp-gauge-component .lh-exp-gauge--faded {
opacity: 0.1;
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper {
font-family: var(--report-font-family-monospace);
text-align: center;
text-decoration: none;
transition: .3s;
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper--pass {
color: var(--color-pass);
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper--average {
color: var(--color-average);
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper--fail {
color: var(--color-fail);
}
.lh-exp-gauge-component .state--expanded {
transition: color .3s;
}
.lh-exp-gauge-component .state--highlight {
color: var(--color-highlight);
}
.lh-exp-gauge-component .lh-exp-gauge__svg-wrapper {
display: flex;
flex-direction: column-reverse;
}

.lh-exp-gauge-component .lh-exp-gauge__label {
fill: var(--report-text-color);
font-family: var(--report-font-family);
font-size: 12px;
}

.lh-exp-gauge-component .lh-exp-gauge__cutout {
opacity: .999;
transition: opacity .3s;
}
.lh-exp-gauge-component .state--highlight .lh-exp-gauge__cutout {
opacity: 0;
}

.lh-exp-gauge-component .lh-exp-gauge__inner {
color: inherit;
}
.lh-exp-gauge-component .lh-exp-gauge__base {
fill: currentcolor;
}


.lh-exp-gauge-component .lh-exp-gauge__arc {
fill: none;
transition: opacity .3s;
}
.lh-exp-gauge-component .lh-exp-gauge__arc--metric {
color: var(--metric-color);
stroke-dashoffset: var(--metric-offset);
opacity: 0.3;
}
.lh-exp-gauge-component .lh-exp-gauge-hovertarget {
color: currentcolor;
opacity: 0.001;
stroke-linecap: butt;
stroke-width: 24;
/* hack. move the hover target out of the center. ideally i tweak the r instead but that rquires considerably more math. */
transform: scale(1.15);
}
.lh-exp-gauge-component .lh-exp-gauge__arc--metric.lh-exp-gauge--miniarc {
opacity: 0;
stroke-dasharray: 0 calc(var(--circle-meas) * var(--radius));
transition: 0s .005s;
}
.lh-exp-gauge-component .state--expanded .lh-exp-gauge__arc--metric.lh-exp-gauge--miniarc {
opacity: .999;
stroke-dasharray: var(--metric-array);
transition: 0.3s; /* calc(.005s + var(--i)*.05s); entrace animation */
}
.lh-exp-gauge-component .state--expanded .lh-exp-gauge__inner .lh-exp-gauge__arc {
opacity: 0;
}


.lh-exp-gauge-component .lh-exp-gauge__percentage {
text-anchor: middle;
dominant-baseline: middle;
opacity: .999;
font-size: calc(var(--radius) * 0.625);
transition: opacity .3s ease-in;
}
.lh-exp-gauge-component .state--highlight .lh-exp-gauge__percentage {
opacity: 0;
}

.lh-exp-gauge-component .lh-exp-gauge__wrapper--fail .lh-exp-gauge__percentage {
fill: var(--color-fail);
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper--average .lh-exp-gauge__percentage {
fill: var(--color-average);
}
.lh-exp-gauge-component .lh-exp-gauge__wrapper--pass .lh-exp-gauge__percentage {
fill: var(--color-pass);
}

.lh-exp-gauge-component .lh-cover {
fill: none;
opacity: .001;
pointer-events: none;
}
.lh-exp-gauge-component .state--expanded .lh-cover {
pointer-events: auto;
}

.lh-exp-gauge-component .metric {
transform: scale(var(--scale-initial));
opacity: 0;
transition: transform .1s .2s ease-out, opacity .3s ease-out;
pointer-events: none;
}
.lh-exp-gauge-component .metric text {
pointer-events: none;
}
.lh-exp-gauge-component .metric__value {
fill: currentcolor;
opacity: 0;
transition: opacity 0.2s;
}
.lh-exp-gauge-component .state--expanded .metric {
transform: scale(1);
opacity: .999;
transition: transform .3s ease-out, opacity .3s ease-in, stroke-width .1s ease-out;
transition-delay: calc(var(--i)*.05s);
pointer-events: auto;
}
.lh-exp-gauge-component .state--highlight .metric {
opacity: .3;
}
.lh-exp-gauge-component .state--highlight .metric--highlight {
opacity: .999;
stroke-width: calc(1.5*var(--stroke-width));
}
.lh-exp-gauge-component .state--highlight .metric--highlight .metric__value {
opacity: 0.999;
}


/*
the initial first load peek
*/
.lh-exp-gauge-component .lh-exp-gauge__bg { /* needed for the use zindex stacking w/ transparency */
fill: var(--report-background-color);
stroke: var(--report-background-color);
}
.lh-exp-gauge-component .state--peek .metric {
transition-delay: 0ms;
animation: peek var(--peek-dur) cubic-bezier(0.46, 0.03, 0.52, 0.96);
animation-fill-mode: forwards;
}
.lh-exp-gauge-component .state--peek .lh-exp-gauge__inner .lh-exp-gauge__arc {
opacity: 1;
}
.lh-exp-gauge-component .state--peek .lh-exp-gauge__arc.lh-exp-gauge--faded {
opacity: 0.3; /* just a tad stronger cuz its fighting with a big solid arg */
}
/* do i need to set expanded and override this? */
.lh-exp-gauge-component .state--peek .lh-exp-gauge__arc--metric.lh-exp-gauge--miniarc {
transition: opacity 0.3s;
}
.lh-exp-gauge-component .state--peek {
color: unset;
}
.lh-exp-gauge-component .state--peek .metric__label {
display: none;
}

.lh-exp-gauge-component .metric__label {
fill: var(--report-text-color);
}

@keyframes peek {
/* biggest it should go is 0.92. smallest is 0.8 */
0% {
transform: scale(0.8);
opacity: 0.8;
}

50% {
transform: scale(0.92);
opacity: 1;
}

100% {
transform: scale(0.8);
opacity: 0.8;
}
}

.lh-exp-gauge-component .wrapper {
width: 620px;
}

/*# sourceURL=report-styles.css */
22 changes: 22 additions & 0 deletions report/assets/templates.html
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,28 @@
</a>
</template>

<!-- Lighthouse score gauge - explodey version -->
<template id="explodeyGauge">
<div class="lh-exp-gauge-component">
<div class="lh-exp-gauge__wrapper" target="_blank">
<div class="lh-exp-gauge__svg-wrapper">
<svg class="lh-exp-gauge">
<g class="lh-exp-gauge__inner">
<circle class="lh-exp-gauge__bg" />
<circle class="lh-exp-gauge__base lh-exp-gauge--faded" />
<circle class="lh-exp-gauge__arc" />
<text class="lh-exp-gauge__percentage"></text>
</g>
<g class="lh-exp-gauge__outer">
<circle class="lh-cover" />
</g>
<text class="lh-exp-gauge__label" text-anchor="middle" x="0" y="60"></text>
</svg>
</div>
</div>
</div>
</template>

<!-- Lighthouse category fraction -->
<template id="fraction">
<a class="lh-fraction__wrapper">
Expand Down
36 changes: 34 additions & 2 deletions report/renderer/components.js

Large diffs are not rendered by default.

33 changes: 30 additions & 3 deletions report/renderer/dom.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
/* eslint-env browser */

/** @typedef {HTMLElementTagNameMap & {[id: string]: HTMLElement}} HTMLElementByTagName */
/** @typedef {SVGElementTagNameMap & {[id: string]: SVGElement}} SVGElementByTagName */
/** @template {string} T @typedef {import('typed-query-selector/parser').ParseSelector<T, Element>} ParseSelector */

import {Util} from '../../shared/util.js';
Expand Down Expand Up @@ -61,6 +62,17 @@ export class DOM {
return element;
}

/**
* @template {string} T
* @param {T} name
* @param {string=} className
* @return {SVGElementByTagName[T]}
*/
createSVGElement(name, className) {
return /** @type {SVGElementByTagName[T]} */ (
this._document.createElementNS('http://www.w3.org/2000/svg', name, className));
}

/**
* @return {!DocumentFragment}
*/
Expand Down Expand Up @@ -239,23 +251,38 @@ export class DOM {
}

/**
* Guaranteed context.querySelector. Always returns an element or throws if
* Typed and guaranteed context.querySelector. Always returns an element or throws if
* nothing matches query.
*
* @template {string} T
* @param {T} query
* @param {ParentNode} context
* @return {ParseSelector<T>}
*/
find(query, context) {
const result = context.querySelector(query);
const result = this.maybeFind(query, context);
if (result === null) {
throw new Error(`query ${query} not found`);
}

return result;
}

/**
* Typed context.querySelector.
*
* @template {string} T
* @param {T} query
* @param {ParentNode} context
* @return {ParseSelector<T> | null}
*/
maybeFind(query, context) {
const result = context.querySelector(query);

// Because we control the report layout and templates, use the simpler
// `typed-query-selector` types that don't require differentiating between
// e.g. HTMLAnchorElement and SVGAElement. See https://github.com/GoogleChrome/lighthouse/issues/12011
return /** @type {ParseSelector<T>} */ (result);
return /** @type {ParseSelector<T> | null} */ (result);
}

/**
Expand Down
Loading

1 comment on commit 6a4c751

@vercel
Copy link

@vercel vercel bot commented on 6a4c751 Oct 2, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

lighthouse – ./

lighthouse-googlechrome.vercel.app
lighthouse-git-main-googlechrome.vercel.app

Please sign in to comment.