@bundle-stats/ui 4.22.3 → 4.23.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/app/app.js +3 -0
- package/lib/app/app.js.map +1 -1
- package/lib/app/app.module.css +12 -2
- package/lib/chart-colors.json +58 -44
- package/lib/components/delta/delta.js +3 -13
- package/lib/components/delta/delta.js.map +1 -1
- package/lib/components/delta/delta.module.css +13 -12
- package/lib/components/delta/index.js.map +1 -1
- package/lib/components/entry-info/entry-info.js +1 -1
- package/lib/components/entry-info/entry-info.js.map +1 -1
- package/lib/components/entry-info/entry-info.module.css +1 -1
- package/lib/components/index.js +3 -1
- package/lib/components/index.js.map +1 -1
- package/lib/components/insight-icon/insight-icon.module.css +6 -6
- package/lib/components/job-name/job-name.js +1 -2
- package/lib/components/job-name/job-name.js.map +1 -1
- package/lib/components/metric-change-legend/index.js +18 -0
- package/lib/components/metric-change-legend/index.js.map +1 -0
- package/lib/components/metric-change-legend/metric-change-legend.js +91 -0
- package/lib/components/metric-change-legend/metric-change-legend.js.map +1 -0
- package/lib/components/metric-change-legend/metric-change-legend.module.css +80 -0
- package/lib/components/metric-run-info/metric-run-info.js +22 -7
- package/lib/components/metric-run-info/metric-run-info.js.map +1 -1
- package/lib/components/metrics-display-selector/metrics-display-selector.js +7 -9
- package/lib/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
- package/lib/components/metrics-display-selector/metrics-display-selector.module.css +0 -25
- package/lib/components/metrics-table-header/metrics-table-header.js +6 -6
- package/lib/components/metrics-table-header/metrics-table-header.js.map +1 -1
- package/lib/components/metrics-table-header/metrics-table-header.module.css +8 -12
- package/lib/components/metrics-table-options/metrics-table-options.js +2 -3
- package/lib/components/metrics-table-options/metrics-table-options.js.map +1 -1
- package/lib/components/metrics-table-title/metrics-table-title.js +1 -1
- package/lib/components/metrics-table-title/metrics-table-title.js.map +1 -1
- package/lib/components/metrics-treemap/metrics-treemap.constants.js +3 -1
- package/lib/components/metrics-treemap/metrics-treemap.constants.js.map +1 -1
- package/lib/components/metrics-treemap/metrics-treemap.js +68 -57
- package/lib/components/metrics-treemap/metrics-treemap.js.map +1 -1
- package/lib/components/metrics-treemap/metrics-treemap.module.css +9 -16
- package/lib/components/metrics-treemap/metrics-treemap.utils.js +72 -16
- package/lib/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
- package/lib/components/run-info/run-info.js +26 -14
- package/lib/components/run-info/run-info.js.map +1 -1
- package/lib/components/run-info/run-info.module.css +35 -26
- package/lib/components/summary/summary.js +9 -10
- package/lib/components/summary/summary.js.map +1 -1
- package/lib/components/summary/summary.module.css +60 -10
- package/lib/constants.js +13 -1
- package/lib/constants.js.map +1 -1
- package/lib/css/variables.css +71 -58
- package/lib/ui/button/button.js +2 -2
- package/lib/ui/button/button.js.map +1 -1
- package/lib/ui/dialog/dialog.js +4 -2
- package/lib/ui/dialog/dialog.js.map +1 -1
- package/lib/ui/dialog/dialog.module.css +22 -0
- package/lib/ui/dropdown/dropdown.js +13 -4
- package/lib/ui/dropdown/dropdown.js.map +1 -1
- package/lib/ui/dropdown/dropdown.module.css +51 -6
- package/lib/ui/filters/filters.js +22 -11
- package/lib/ui/filters/filters.js.map +1 -1
- package/lib/ui/filters/filters.module.css +0 -14
- package/lib/ui/hover-card/hover-card.js +7 -1
- package/lib/ui/hover-card/hover-card.js.map +1 -1
- package/lib/ui/hover-card/hover-card.module.css +14 -0
- package/lib/ui/table/table.module.css +0 -1
- package/lib/ui/tooltip/tooltip.js +6 -1
- package/lib/ui/tooltip/tooltip.js.map +1 -1
- package/lib/ui/tooltip/tooltip.module.css +11 -0
- package/lib-esm/app/app.js +4 -1
- package/lib-esm/app/app.js.map +1 -1
- package/lib-esm/app/app.module.css +12 -2
- package/lib-esm/chart-colors.json +58 -44
- package/lib-esm/components/delta/delta.js +3 -13
- package/lib-esm/components/delta/delta.js.map +1 -1
- package/lib-esm/components/delta/delta.module.css +13 -12
- package/lib-esm/components/delta/index.js.map +1 -1
- package/lib-esm/components/entry-info/entry-info.js +1 -1
- package/lib-esm/components/entry-info/entry-info.js.map +1 -1
- package/lib-esm/components/entry-info/entry-info.module.css +1 -1
- package/lib-esm/components/index.js +1 -0
- package/lib-esm/components/index.js.map +1 -1
- package/lib-esm/components/insight-icon/insight-icon.module.css +6 -6
- package/lib-esm/components/job-name/job-name.js +1 -2
- package/lib-esm/components/job-name/job-name.js.map +1 -1
- package/lib-esm/components/metric-change-legend/index.js +2 -0
- package/lib-esm/components/metric-change-legend/index.js.map +1 -0
- package/lib-esm/components/metric-change-legend/metric-change-legend.js +84 -0
- package/lib-esm/components/metric-change-legend/metric-change-legend.js.map +1 -0
- package/lib-esm/components/metric-change-legend/metric-change-legend.module.css +80 -0
- package/lib-esm/components/metric-run-info/metric-run-info.js +22 -7
- package/lib-esm/components/metric-run-info/metric-run-info.js.map +1 -1
- package/lib-esm/components/metrics-display-selector/metrics-display-selector.js +7 -9
- package/lib-esm/components/metrics-display-selector/metrics-display-selector.js.map +1 -1
- package/lib-esm/components/metrics-display-selector/metrics-display-selector.module.css +0 -25
- package/lib-esm/components/metrics-table-header/metrics-table-header.js +6 -6
- package/lib-esm/components/metrics-table-header/metrics-table-header.js.map +1 -1
- package/lib-esm/components/metrics-table-header/metrics-table-header.module.css +8 -12
- package/lib-esm/components/metrics-table-options/metrics-table-options.js +3 -4
- package/lib-esm/components/metrics-table-options/metrics-table-options.js.map +1 -1
- package/lib-esm/components/metrics-table-title/metrics-table-title.js +1 -1
- package/lib-esm/components/metrics-table-title/metrics-table-title.js.map +1 -1
- package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js +2 -0
- package/lib-esm/components/metrics-treemap/metrics-treemap.constants.js.map +1 -1
- package/lib-esm/components/metrics-treemap/metrics-treemap.js +74 -63
- package/lib-esm/components/metrics-treemap/metrics-treemap.js.map +1 -1
- package/lib-esm/components/metrics-treemap/metrics-treemap.module.css +9 -16
- package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js +71 -17
- package/lib-esm/components/metrics-treemap/metrics-treemap.utils.js.map +1 -1
- package/lib-esm/components/run-info/run-info.js +26 -14
- package/lib-esm/components/run-info/run-info.js.map +1 -1
- package/lib-esm/components/run-info/run-info.module.css +35 -26
- package/lib-esm/components/summary/summary.js +10 -11
- package/lib-esm/components/summary/summary.js.map +1 -1
- package/lib-esm/components/summary/summary.module.css +60 -10
- package/lib-esm/constants.js +12 -0
- package/lib-esm/constants.js.map +1 -1
- package/lib-esm/css/variables.css +71 -58
- package/lib-esm/ui/button/button.js +2 -2
- package/lib-esm/ui/button/button.js.map +1 -1
- package/lib-esm/ui/dialog/dialog.js +4 -2
- package/lib-esm/ui/dialog/dialog.js.map +1 -1
- package/lib-esm/ui/dialog/dialog.module.css +22 -0
- package/lib-esm/ui/dropdown/dropdown.js +11 -3
- package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
- package/lib-esm/ui/dropdown/dropdown.module.css +51 -6
- package/lib-esm/ui/filters/filters.js +23 -12
- package/lib-esm/ui/filters/filters.js.map +1 -1
- package/lib-esm/ui/filters/filters.module.css +0 -14
- package/lib-esm/ui/hover-card/hover-card.js +7 -1
- package/lib-esm/ui/hover-card/hover-card.js.map +1 -1
- package/lib-esm/ui/hover-card/hover-card.module.css +14 -0
- package/lib-esm/ui/table/table.module.css +0 -1
- package/lib-esm/ui/tooltip/tooltip.js +6 -1
- package/lib-esm/ui/tooltip/tooltip.js.map +1 -1
- package/lib-esm/ui/tooltip/tooltip.module.css +11 -0
- package/package.json +16 -16
- package/src/app/app.jsx +6 -1
- package/src/app/app.module.css +12 -2
- package/src/chart-colors.json +58 -44
- package/src/components/delta/delta.module.css +13 -12
- package/src/components/delta/delta.tsx +32 -0
- package/src/components/entry-info/entry-info.module.css +1 -1
- package/src/components/entry-info/entry-info.tsx +2 -2
- package/src/components/index.ts +3 -0
- package/src/components/insight-icon/insight-icon.module.css +6 -6
- package/src/components/job-name/job-name.jsx +2 -3
- package/src/components/metric-change-legend/index.ts +1 -0
- package/src/components/metric-change-legend/metric-change-legend.module.css +80 -0
- package/src/components/metric-change-legend/metric-change-legend.stories.tsx +13 -0
- package/src/components/metric-change-legend/metric-change-legend.tsx +148 -0
- package/src/components/metric-run-info/metric-run-info.tsx +32 -17
- package/src/components/metrics-display-selector/metrics-display-selector.module.css +0 -25
- package/src/components/metrics-display-selector/metrics-display-selector.tsx +25 -37
- package/src/components/metrics-table-header/metrics-table-header.module.css +8 -12
- package/src/components/metrics-table-header/metrics-table-header.tsx +5 -6
- package/src/components/metrics-table-options/metrics-table-options.tsx +5 -6
- package/src/components/metrics-table-title/metrics-table-title.jsx +1 -1
- package/src/components/metrics-treemap/metrics-treemap.constants.ts +8 -0
- package/src/components/metrics-treemap/metrics-treemap.module.css +9 -16
- package/src/components/metrics-treemap/metrics-treemap.tsx +160 -135
- package/src/components/metrics-treemap/metrics-treemap.utils.ts +141 -27
- package/src/components/run-info/run-info.module.css +35 -26
- package/src/components/run-info/run-info.stories.tsx +16 -10
- package/src/components/run-info/run-info.tsx +132 -73
- package/src/components/summary/summary.module.css +60 -10
- package/src/components/summary/summary.tsx +47 -50
- package/src/constants.ts +13 -0
- package/src/css/variables.css +71 -58
- package/src/ui/button/button.tsx +2 -1
- package/src/ui/dialog/dialog.module.css +22 -0
- package/src/ui/dialog/dialog.tsx +9 -2
- package/src/ui/dropdown/dropdown.module.css +51 -6
- package/src/ui/dropdown/dropdown.tsx +17 -2
- package/src/ui/filters/filters.module.css +0 -14
- package/src/ui/filters/filters.tsx +111 -47
- package/src/ui/hover-card/hover-card.module.css +14 -0
- package/src/ui/hover-card/hover-card.tsx +7 -1
- package/src/ui/table/table.module.css +0 -1
- package/src/ui/tooltip/tooltip.module.css +11 -0
- package/src/ui/tooltip/tooltip.tsx +6 -1
- package/types/components/delta/delta.d.ts +7 -21
- package/types/components/delta/index.d.ts +1 -1
- package/types/components/index.d.ts +3 -0
- package/types/components/metric-change-legend/index.d.ts +1 -0
- package/types/components/metric-change-legend/metric-change-legend.d.ts +4 -0
- package/types/components/metric-run-info/metric-run-info.d.ts +3 -6
- package/types/components/metrics-treemap/metrics-treemap.constants.d.ts +2 -0
- package/types/components/metrics-treemap/metrics-treemap.utils.d.ts +11 -5
- package/types/components/run-info/run-info.d.ts +16 -7
- package/types/constants.d.ts +12 -0
- package/types/ui/dialog/dialog.d.ts +3 -2
- package/types/ui/dropdown/dropdown.d.ts +4 -1
- package/types/ui/filters/filters.d.ts +2 -1
- package/vitest.config.ts +4 -0
- package/lib/components/metrics-table-options/metrics-table-options.module.css +0 -15
- package/lib-esm/components/metrics-table-options/metrics-table-options.module.css +0 -15
- package/src/components/delta/delta.jsx +0 -22
- package/src/components/metrics-table-options/metrics-table-options.module.css +0 -15
- /package/src/components/delta/{index.js → index.ts} +0 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
|
|
4
|
+
import { FlexStack } from '../../layout/flex-stack';
|
|
5
|
+
import { Stack } from '../../layout/stack';
|
|
6
|
+
import { HoverCard } from '../../ui/hover-card';
|
|
7
|
+
import { Table } from '../../ui/table';
|
|
8
|
+
import css from './metric-change-legend.module.css';
|
|
9
|
+
import { Separator } from '../../layout';
|
|
10
|
+
|
|
11
|
+
type ChangeKind = 'improvement' | 'regression' | 'neutral' | 'no-change';
|
|
12
|
+
type ChangeKindVariant = 'low' | 'medium' | 'high';
|
|
13
|
+
|
|
14
|
+
type BarProps = {
|
|
15
|
+
className?: string;
|
|
16
|
+
kind: ChangeKind;
|
|
17
|
+
variants: ChangeKindVariant[];
|
|
18
|
+
size?: 'medium' | 'large';
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const Variants = (props: BarProps) => {
|
|
22
|
+
const { className, kind, variants, size = 'medium' } = props;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<span className={cx(css.variants, css[`bar-${kind}`], css[size], className)}>
|
|
26
|
+
{variants.map((variant) => (
|
|
27
|
+
<span key={variant} className={cx(css.variant, css[`variant-${variant}`])} />
|
|
28
|
+
))}
|
|
29
|
+
</span>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type ChangeMagnitudeInfoProps = {
|
|
34
|
+
kind: 'improvement' | 'regression';
|
|
35
|
+
impact: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const ChangeMagnitudeInfo = (props: ChangeMagnitudeInfoProps) => {
|
|
39
|
+
const { kind, impact } = props;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Stack space="small">
|
|
43
|
+
<p>
|
|
44
|
+
Changes flagged as <strong>{kind}s</strong> have a {impact} impact on user performance.
|
|
45
|
+
</p>
|
|
46
|
+
<p>
|
|
47
|
+
The report shows different intensity colors depending on the magnitude of the percentage
|
|
48
|
+
change.
|
|
49
|
+
</p>
|
|
50
|
+
<Stack space="xxsmall">
|
|
51
|
+
<Separator />
|
|
52
|
+
<FlexStack alignItems="center" space="xxsmall">
|
|
53
|
+
<Variants kind={kind} variants={['low']} size="large" />
|
|
54
|
+
Change is smaller or equal than <strong>5%</strong>
|
|
55
|
+
</FlexStack>
|
|
56
|
+
<Separator />
|
|
57
|
+
<FlexStack alignItems="center" space="xxsmall">
|
|
58
|
+
<Variants kind={kind} variants={['medium']} size="large" />
|
|
59
|
+
Change is smaller or equal than <strong>50%</strong>
|
|
60
|
+
</FlexStack>
|
|
61
|
+
<Separator />
|
|
62
|
+
<FlexStack alignItems="center" space="xxsmall">
|
|
63
|
+
<Variants kind={kind} variants={['high']} size="large" />
|
|
64
|
+
Change is larger than <strong>50%</strong>
|
|
65
|
+
</FlexStack>
|
|
66
|
+
</Stack>
|
|
67
|
+
</Stack>
|
|
68
|
+
);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const ImprovementInfo = () => <ChangeMagnitudeInfo kind="improvement" impact="positive" />;
|
|
72
|
+
const RegressionInfo = () => <ChangeMagnitudeInfo kind="regression" impact="negative" />;
|
|
73
|
+
|
|
74
|
+
const NeutralInfo = () => (
|
|
75
|
+
<Stack space="small">
|
|
76
|
+
<p>
|
|
77
|
+
<strong>Neutral</strong> changes do not have a clear positive or negative impact on user
|
|
78
|
+
performance.
|
|
79
|
+
</p>
|
|
80
|
+
</Stack>
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
const NoChangeInfo = () => (
|
|
84
|
+
<Stack space="small">
|
|
85
|
+
<p>
|
|
86
|
+
The metric value is <strong>unchanged</strong> between the compared builds.
|
|
87
|
+
</p>
|
|
88
|
+
</Stack>
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
type ChangeConfig = {
|
|
92
|
+
id: ChangeKind;
|
|
93
|
+
label: string;
|
|
94
|
+
variants: ChangeKindVariant[];
|
|
95
|
+
info: ReactNode;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const ITEMS: ChangeConfig[] = [
|
|
99
|
+
{
|
|
100
|
+
id: 'improvement',
|
|
101
|
+
label: 'Improvement',
|
|
102
|
+
variants: ['low', 'medium', 'high'],
|
|
103
|
+
info: <ImprovementInfo />,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: 'regression',
|
|
107
|
+
label: 'Regression',
|
|
108
|
+
variants: ['low', 'medium', 'high'],
|
|
109
|
+
info: <RegressionInfo />,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'neutral',
|
|
113
|
+
label: 'Neutral',
|
|
114
|
+
variants: ['medium'],
|
|
115
|
+
info: <NeutralInfo />,
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: 'no-change',
|
|
119
|
+
label: 'No change',
|
|
120
|
+
variants: ['medium'],
|
|
121
|
+
info: <NoChangeInfo />,
|
|
122
|
+
},
|
|
123
|
+
];
|
|
124
|
+
|
|
125
|
+
export interface MetricChangeLegendProps extends React.ComponentProps<'div'> {}
|
|
126
|
+
|
|
127
|
+
export const MetricChangeLegend = (props: MetricChangeLegendProps) => {
|
|
128
|
+
const { className, ...restProps } = props;
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<FlexStack inline space="small" className={cx(css.root, className)} {...restProps}>
|
|
132
|
+
{ITEMS.map(({ id, variants, label, info }) => (
|
|
133
|
+
<HoverCard
|
|
134
|
+
key={id}
|
|
135
|
+
anchorClassName={css.itemAnchor}
|
|
136
|
+
label={
|
|
137
|
+
<FlexStack inline alignItems="center" space="xxsmall" className={css.item}>
|
|
138
|
+
<Variants kind={id} variants={variants} className={css.itemVariants} />
|
|
139
|
+
<span className={css.itemLabel}>{label}</span>
|
|
140
|
+
</FlexStack>
|
|
141
|
+
}
|
|
142
|
+
>
|
|
143
|
+
{info}
|
|
144
|
+
</HoverCard>
|
|
145
|
+
))}
|
|
146
|
+
</FlexStack>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { type MouseEvent, useCallback, useMemo, ElementType } from 'react';
|
|
2
|
-
import { getGlobalMetricType, getMetricRunInfo } from '@bundle-stats/utils';
|
|
2
|
+
import { getGlobalMetricType, getMetricRunInfo, MetricTypes } from '@bundle-stats/utils';
|
|
3
3
|
import { Focusable } from 'ariakit/focusable';
|
|
4
4
|
|
|
5
5
|
import { Stack } from '../../layout/stack';
|
|
@@ -8,11 +8,11 @@ import { Icon } from '../../ui/icon';
|
|
|
8
8
|
import { RunInfo, RunInfoProps } from '../run-info';
|
|
9
9
|
import css from './metric-run-info.module.css';
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
type MetricInfoProps = {
|
|
12
12
|
title: string;
|
|
13
13
|
description?: string;
|
|
14
14
|
url?: string;
|
|
15
|
-
}
|
|
15
|
+
};
|
|
16
16
|
|
|
17
17
|
const MetricHoverCard = ({ title, description, url }: MetricInfoProps) => {
|
|
18
18
|
// The component parent can be rendered inside a link or a button
|
|
@@ -50,17 +50,14 @@ const MetricHoverCard = ({ title, description, url }: MetricInfoProps) => {
|
|
|
50
50
|
);
|
|
51
51
|
};
|
|
52
52
|
|
|
53
|
-
export
|
|
53
|
+
export type MetricRunInfoProps = {
|
|
54
54
|
metricId: string;
|
|
55
55
|
current: number;
|
|
56
56
|
baseline?: number;
|
|
57
|
-
showDelta?: boolean;
|
|
58
57
|
showMetricDescription?: boolean;
|
|
59
|
-
showBaseline?: boolean;
|
|
60
58
|
titleWrapper?: ElementType;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
59
|
+
showDeltaValue?: boolean;
|
|
60
|
+
} & Pick<RunInfoProps, 'showDelta' | 'showBaseline' | 'size' | 'loading'>;
|
|
64
61
|
|
|
65
62
|
export const MetricRunInfo = (props: MetricRunInfoProps & React.ComponentProps<'div'>) => {
|
|
66
63
|
const {
|
|
@@ -92,16 +89,37 @@ export const MetricRunInfo = (props: MetricRunInfoProps & React.ComponentProps<'
|
|
|
92
89
|
[CustomTitleWrapper, metric.label],
|
|
93
90
|
);
|
|
94
91
|
|
|
92
|
+
const baselineProps = useMemo(() => {
|
|
93
|
+
if (showBaseline) {
|
|
94
|
+
return {
|
|
95
|
+
showBaseline,
|
|
96
|
+
baseline: metric.formatter(baseline),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return { showBaseline };
|
|
101
|
+
}, [showBaseline, baseline]);
|
|
102
|
+
|
|
95
103
|
const deltaProps = useMemo(() => {
|
|
96
|
-
if (!showDelta || metric.skipDelta
|
|
97
|
-
return {
|
|
104
|
+
if (!showDelta || metric.skipDelta) {
|
|
105
|
+
return {
|
|
106
|
+
showDelta: false,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// If the delta data is missing, do not render the dats
|
|
111
|
+
if (!('delta' in metricRunInfo)) {
|
|
112
|
+
return {
|
|
113
|
+
showDelta: false,
|
|
114
|
+
};
|
|
98
115
|
}
|
|
99
116
|
|
|
100
117
|
return {
|
|
101
|
-
|
|
118
|
+
showDelta: true,
|
|
102
119
|
deltaType: metricRunInfo.deltaType,
|
|
120
|
+
deltaPercentage: metricRunInfo.displayDeltaPercentage,
|
|
103
121
|
};
|
|
104
|
-
}, [metricRunInfo]);
|
|
122
|
+
}, [metric, metricRunInfo, showDelta]);
|
|
105
123
|
|
|
106
124
|
return (
|
|
107
125
|
<RunInfo
|
|
@@ -109,10 +127,7 @@ export const MetricRunInfo = (props: MetricRunInfoProps & React.ComponentProps<'
|
|
|
109
127
|
titleHoverCard={titleHoverCard}
|
|
110
128
|
enhance
|
|
111
129
|
current={metricRunInfo.displayValue}
|
|
112
|
-
|
|
113
|
-
{...(showBaseline && {
|
|
114
|
-
baseline: metric.formatter(baseline),
|
|
115
|
-
})}
|
|
130
|
+
{...baselineProps}
|
|
116
131
|
{...deltaProps}
|
|
117
132
|
{...restProps}
|
|
118
133
|
/>
|
|
@@ -7,31 +7,6 @@
|
|
|
7
7
|
padding: calc(var(--space-xxsmall) - 1px);
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
.dropdownGroupAnchor {
|
|
11
|
-
border: none;
|
|
12
|
-
border-radius: 0;
|
|
13
|
-
position: relative;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.dropdownGroupAnchor::before {
|
|
17
|
-
content: '';
|
|
18
|
-
display: block;
|
|
19
|
-
width: 1px;
|
|
20
|
-
background: var(--color-outline-dark);
|
|
21
|
-
position: absolute;
|
|
22
|
-
left: 0;
|
|
23
|
-
top: var(--space-xxxsmall);
|
|
24
|
-
bottom: var(--space-xxxsmall);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
.dropdownGroupAnchor:hover,
|
|
28
|
-
.dropdownGroupAnchor:focus,
|
|
29
|
-
.dropdownGroupAnchor:active {
|
|
30
|
-
border-color: var(--color-outline);
|
|
31
|
-
box-shadow: none;
|
|
32
|
-
background: none;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
10
|
.dropdownGroup:hover {
|
|
36
11
|
border-color: var(--color-outline-dark);
|
|
37
12
|
transition: var(--transition-in);
|
|
@@ -90,44 +90,32 @@ export const MetricsDisplaySelector = (
|
|
|
90
90
|
);
|
|
91
91
|
|
|
92
92
|
return (
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
glyph={Icon.ICONS.CHEVRON_DOWN}
|
|
104
|
-
placement="bottom-end"
|
|
105
|
-
shift={-1}
|
|
106
|
-
className={css.dropdownGroupAnchor}
|
|
107
|
-
>
|
|
108
|
-
{displayGroupsData.map((displayGroupData) => {
|
|
109
|
-
const isGroupActive = isActive && displayGroupData.value === groupBy;
|
|
93
|
+
<Dropdown
|
|
94
|
+
label={displayProps.label}
|
|
95
|
+
glyph={displayProps.glyph}
|
|
96
|
+
placement="bottom-end"
|
|
97
|
+
shift={-1}
|
|
98
|
+
className={itemClassName}
|
|
99
|
+
key={displayType}
|
|
100
|
+
>
|
|
101
|
+
{displayGroupsData.map((displayGroupData) => {
|
|
102
|
+
const isGroupActive = isActive && displayGroupData.value === groupBy;
|
|
110
103
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
</DropdownItem>
|
|
127
|
-
);
|
|
128
|
-
})}
|
|
129
|
-
</Dropdown>
|
|
130
|
-
</FlexStack>
|
|
104
|
+
return (
|
|
105
|
+
<DropdownItem
|
|
106
|
+
onClick={() => onSelect(displayType, displayGroupData.value)}
|
|
107
|
+
isActive={isGroupActive}
|
|
108
|
+
className={cx(css.dropdownItem, isGroupActive && css.dropdownItemActive)}
|
|
109
|
+
key={displayGroupData.value}
|
|
110
|
+
>
|
|
111
|
+
<FlexStack space="xxxsmall" alignItems="center">
|
|
112
|
+
<Icon glyph={Icon.ICONS.CHECK} size="small" className={css.dropdownItemIcon} />
|
|
113
|
+
<span>{displayGroupData.label}</span>
|
|
114
|
+
</FlexStack>
|
|
115
|
+
</DropdownItem>
|
|
116
|
+
);
|
|
117
|
+
})}
|
|
118
|
+
</Dropdown>
|
|
131
119
|
);
|
|
132
120
|
})}
|
|
133
121
|
</ControlGroup>
|
|
@@ -4,23 +4,23 @@
|
|
|
4
4
|
padding-bottom: var(--space-xxsmall);
|
|
5
5
|
}
|
|
6
6
|
|
|
7
|
-
.root .
|
|
7
|
+
.root .colMetric {
|
|
8
8
|
width: 55%;
|
|
9
9
|
vertical-align: middle;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
-
.root .
|
|
12
|
+
.root .colJob {
|
|
13
13
|
padding-top: var(--space-xxsmall);
|
|
14
14
|
text-align: right;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
.root .
|
|
17
|
+
.root .colValue {
|
|
18
18
|
text-align: right;
|
|
19
19
|
vertical-align: baseline;
|
|
20
20
|
width: 15%;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
.root .
|
|
23
|
+
.root .colDelta {
|
|
24
24
|
text-align: right;
|
|
25
25
|
font-size: var(--size-xsmall);
|
|
26
26
|
vertical-align: baseline;
|
|
@@ -28,21 +28,17 @@
|
|
|
28
28
|
color: pink;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
.root .
|
|
31
|
+
.root .colDeltaPercentage {
|
|
32
32
|
width: 5%;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
.jobName {
|
|
36
|
-
white-space: nowrap;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
35
|
/* columns overrides for showHeaderSum */
|
|
40
|
-
.showHeaderSum .
|
|
36
|
+
.showHeaderSum .colJob {
|
|
41
37
|
border-bottom: 0;
|
|
42
|
-
padding-bottom:
|
|
38
|
+
padding-bottom: var(--space-xxxsmall);
|
|
43
39
|
}
|
|
44
40
|
|
|
45
|
-
.showHeaderSum .
|
|
41
|
+
.showHeaderSum .colSum {
|
|
46
42
|
padding-top: 0;
|
|
47
43
|
font-size: var(--size-small);
|
|
48
44
|
vertical-align: middle;
|
|
@@ -34,11 +34,10 @@ const JobColumn = ({ job, isBaseline }: JobColumnProps) => {
|
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
return (
|
|
37
|
-
<Table.Th className={cx(css.col, css.
|
|
37
|
+
<Table.Th className={cx(css.col, css.colJob)} colSpan={colSpan}>
|
|
38
38
|
<JobName
|
|
39
39
|
title={isBaseline ? I18N.BASELINE_TITLE : I18N.CURRENT_TITLE}
|
|
40
40
|
internalBuildNumber={internalBuildNumber}
|
|
41
|
-
className={css.jobName}
|
|
42
41
|
>
|
|
43
42
|
{label}
|
|
44
43
|
</JobName>
|
|
@@ -65,7 +64,7 @@ const SumColumn = ({ rows, isBaseline, runIndex, updateSort, sort }: ColumnSumPr
|
|
|
65
64
|
|
|
66
65
|
return (
|
|
67
66
|
<>
|
|
68
|
-
<Table.Th className={cx(css.col, css.
|
|
67
|
+
<Table.Th className={cx(css.col, css.colValue, css.colSum)}>
|
|
69
68
|
<SortButton
|
|
70
69
|
fieldPath={fieldPath}
|
|
71
70
|
fieldName="value"
|
|
@@ -78,7 +77,7 @@ const SumColumn = ({ rows, isBaseline, runIndex, updateSort, sort }: ColumnSumPr
|
|
|
78
77
|
</Table.Th>
|
|
79
78
|
{!isBaseline && (
|
|
80
79
|
<>
|
|
81
|
-
<Table.Th className={cx(css.col, css.
|
|
80
|
+
<Table.Th className={cx(css.col, css.colDelta, css.colSum)}>
|
|
82
81
|
<SortButton
|
|
83
82
|
fieldPath={fieldPath}
|
|
84
83
|
fieldName="delta"
|
|
@@ -91,7 +90,7 @@ const SumColumn = ({ rows, isBaseline, runIndex, updateSort, sort }: ColumnSumPr
|
|
|
91
90
|
)}
|
|
92
91
|
</SortButton>
|
|
93
92
|
</Table.Th>
|
|
94
|
-
<Table.Th className={cx(css.col, css.
|
|
93
|
+
<Table.Th className={cx(css.col, css.colDelta, css.colDeltaPercentage, css.colSum)}>
|
|
95
94
|
<SortButton
|
|
96
95
|
fieldPath={fieldPath}
|
|
97
96
|
fieldName="deltaPercentage"
|
|
@@ -147,7 +146,7 @@ export const MetricsTableHeader = (
|
|
|
147
146
|
return (
|
|
148
147
|
<Table.THead className={rootClassName}>
|
|
149
148
|
<Table.Tr>
|
|
150
|
-
<Table.Th className={cx(css.col, css.
|
|
149
|
+
<Table.Th className={cx(css.col, css.colMetric)} rowSpan={showSum ? 2 : 1}>
|
|
151
150
|
{metricTitle || ' '}
|
|
152
151
|
</Table.Th>
|
|
153
152
|
{jobs.map((job, runIndex) => (
|
|
@@ -2,8 +2,7 @@ import type { ComponentProps } from 'react';
|
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
4
|
import I18N from '../../i18n';
|
|
5
|
-
import { Dropdown, DropdownItem } from '../../ui/dropdown';
|
|
6
|
-
import css from './metrics-table-options.module.css';
|
|
5
|
+
import { Dropdown, DropdownGroup, DropdownItem } from '../../ui/dropdown';
|
|
7
6
|
|
|
8
7
|
type MetricsTableOptionsProps = {
|
|
9
8
|
onViewAllClick?: () => void;
|
|
@@ -16,18 +15,18 @@ export const MetricsTableOptions = (props: MetricsTableOptionsProps) => {
|
|
|
16
15
|
|
|
17
16
|
return (
|
|
18
17
|
<Dropdown glyph="more-vertical" placement="bottom-end" {...restProps}>
|
|
19
|
-
<
|
|
18
|
+
<DropdownGroup>
|
|
20
19
|
{onResetClick && <DropdownItem onClick={onResetClick}>{I18N.RESET_FILTERS}</DropdownItem>}
|
|
21
20
|
{onViewAllClick && <DropdownItem onClick={onViewAllClick}>{I18N.VIEW_ALL}</DropdownItem>}
|
|
22
|
-
</
|
|
23
|
-
<
|
|
21
|
+
</DropdownGroup>
|
|
22
|
+
<DropdownGroup>
|
|
24
23
|
{onExportClick && (
|
|
25
24
|
<>
|
|
26
25
|
<DropdownItem onClick={() => onExportClick('csv')}>{I18N.EXPORT_CSV}</DropdownItem>
|
|
27
26
|
<DropdownItem onClick={() => onExportClick('json')}>{I18N.EXPORT_JSON}</DropdownItem>
|
|
28
27
|
</>
|
|
29
28
|
)}
|
|
30
|
-
</
|
|
29
|
+
</DropdownGroup>
|
|
31
30
|
</Dropdown>
|
|
32
31
|
);
|
|
33
32
|
};
|
|
@@ -15,7 +15,7 @@ export const MetricsTableTitle = (props) => {
|
|
|
15
15
|
const rootClassName = cx(css.root, className);
|
|
16
16
|
|
|
17
17
|
return (
|
|
18
|
-
<Stack space="
|
|
18
|
+
<Stack space="xxxsmall" className={rootClassName}>
|
|
19
19
|
<FlexStack space="xxxsmall" alignItems="center" as="h3" className={css.title}>
|
|
20
20
|
<span>{title}</span>
|
|
21
21
|
|
|
@@ -55,6 +55,14 @@ export type TileGroupSizeDisplay = 'minimal' | 'small' | 'default';
|
|
|
55
55
|
|
|
56
56
|
export type TileSizeDisplay = 'minimal' | 'small' | 'default';
|
|
57
57
|
|
|
58
|
+
/**
|
|
59
|
+
* DOM marker set on every tile and tile group title (see `metrics-treemap.tsx`).
|
|
60
|
+
* `MetricsTreemap` uses it to resolve the hovered node from a single delegated
|
|
61
|
+
* pointer handler, instead of attaching hover listeners to every cell.
|
|
62
|
+
*/
|
|
63
|
+
export const NODE_ID_ATTRIBUTE = 'data-treemap-id';
|
|
64
|
+
export const NODE_ID_SELECTOR = `[${NODE_ID_ATTRIBUTE}]`;
|
|
65
|
+
|
|
58
66
|
export const SQUARIFY_RATIO = 1.66;
|
|
59
67
|
export const PADDING_OUTER = 1;
|
|
60
68
|
export const PADDING_INNER = 2;
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
* Tile group
|
|
21
21
|
*/
|
|
22
22
|
.tileGroup {
|
|
23
|
+
border-radius: var(--radius-xsmall);
|
|
23
24
|
position: absolute;
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
.tileGroupTitleContent {
|
|
32
33
|
width: 100%;
|
|
33
34
|
padding: var(--space-xxxsmall) 2px var(--space-xxxsmall) var(--space-xxsmall);
|
|
35
|
+
border-radius: var(--radius-xsmall);
|
|
34
36
|
display: flex;
|
|
35
37
|
align-items: center;
|
|
36
38
|
color: var(--color-text);
|
|
@@ -66,12 +68,6 @@
|
|
|
66
68
|
.tileGroup {
|
|
67
69
|
transition: var(--transition-out);
|
|
68
70
|
transition-property: background-color, outline;
|
|
69
|
-
border-radius: var(--radius-xsmall);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
.tileGroup--minimal,
|
|
73
|
-
.tileGroup--small {
|
|
74
|
-
border-radius: calc(var(--radius-xsmall) / 2);
|
|
75
71
|
}
|
|
76
72
|
|
|
77
73
|
.tileGroup--minimal .tileGroupTitle,
|
|
@@ -136,9 +132,8 @@
|
|
|
136
132
|
position: absolute;
|
|
137
133
|
appearance: none;
|
|
138
134
|
border: 0;
|
|
139
|
-
border-radius:
|
|
135
|
+
border-radius: var(--radius-xsmall);
|
|
140
136
|
padding: 0;
|
|
141
|
-
border-radius: calc(var(--radius-xsmall) / 2);
|
|
142
137
|
background: var(--color-background);
|
|
143
138
|
display: flex;
|
|
144
139
|
align-items: center;
|
|
@@ -159,6 +154,7 @@
|
|
|
159
154
|
top: 0;
|
|
160
155
|
width: 100%;
|
|
161
156
|
height: 100%;
|
|
157
|
+
border-radius: inherit;
|
|
162
158
|
background-color: currentColor;
|
|
163
159
|
}
|
|
164
160
|
|
|
@@ -170,9 +166,10 @@
|
|
|
170
166
|
display: flex;
|
|
171
167
|
flex-flow: column;
|
|
172
168
|
justify-content: center;
|
|
173
|
-
padding: var(--space-xxsmall)
|
|
169
|
+
padding: var(--space-xxsmall);
|
|
174
170
|
gap: var(--space-xxxsmall);
|
|
175
171
|
line-height: var(--line-height-heading);
|
|
172
|
+
cursor: default;
|
|
176
173
|
}
|
|
177
174
|
|
|
178
175
|
/** Align label to other elements on the first column cells */
|
|
@@ -213,7 +210,7 @@
|
|
|
213
210
|
/** Tile size variation */
|
|
214
211
|
.tileSizeSmall .tileContent {
|
|
215
212
|
padding: var(--space-xxxsmall);
|
|
216
|
-
font-size:
|
|
213
|
+
font-size: var(--size-xsmall);
|
|
217
214
|
}
|
|
218
215
|
|
|
219
216
|
.tileSizeSmall .tileContentLabel {
|
|
@@ -298,11 +295,6 @@
|
|
|
298
295
|
}
|
|
299
296
|
|
|
300
297
|
/** tooltip */
|
|
301
|
-
.tileContentTooltipAnchor {
|
|
302
|
-
width: 100%;
|
|
303
|
-
height: 100%;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
298
|
.tooltip {
|
|
307
299
|
z-index: var(--layer-high);
|
|
308
300
|
padding: var(--space-xsmall) var(--space-small);
|
|
@@ -326,7 +318,8 @@
|
|
|
326
318
|
font-size: var(--size-small);
|
|
327
319
|
}
|
|
328
320
|
|
|
329
|
-
/* prevent tooltip portal wrapper from capturing events
|
|
321
|
+
/* prevent the tooltip portal wrapper from capturing pointer events - the
|
|
322
|
+
treemap relies on pointer events reaching the canvas to track the hovered cell */
|
|
330
323
|
div[role='presentation']:has(.tooltip) {
|
|
331
324
|
pointer-events: none;
|
|
332
325
|
}
|