@bundle-stats/ui 4.22.2 → 4.23.0-beta.1
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/.babelrc.js +65 -24
- package/globals.d.ts +13 -0
- package/lib/app/app.js +3 -0
- package/lib/app/app.js.map +1 -1
- package/lib/app/app.module.css +11 -1
- package/lib/components/bundle-modules/index.js.map +1 -1
- 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/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 +69 -0
- package/lib/components/metric-run-info/metric-run-info.js +30 -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 +8 -8
- 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 +1 -1
- 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/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/default.css +1 -1
- package/lib/css/variables.css +71 -58
- package/lib/hooks/rows-sort.js +13 -12
- package/lib/hooks/rows-sort.js.map +1 -1
- 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 +4 -3
- package/lib/ui/dropdown/dropdown.js.map +1 -1
- package/lib/ui/dropdown/dropdown.module.css +11 -0
- package/lib/ui/empty-set/empty-set.js +3 -3
- package/lib/ui/empty-set/empty-set.js.map +1 -1
- package/lib/ui/hover-card/hover-card.js +1 -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 +1 -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 +11 -1
- package/lib-esm/components/bundle-modules/index.js.map +1 -1
- 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/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 +69 -0
- package/lib-esm/components/metric-run-info/metric-run-info.js +31 -8
- 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 +8 -8
- 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 +1 -1
- 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/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/default.css +1 -1
- package/lib-esm/css/variables.css +71 -58
- package/lib-esm/hooks/rows-sort.js +10 -8
- package/lib-esm/hooks/rows-sort.js.map +1 -1
- 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 +4 -3
- package/lib-esm/ui/dropdown/dropdown.js.map +1 -1
- package/lib-esm/ui/dropdown/dropdown.module.css +11 -0
- package/lib-esm/ui/empty-set/empty-set.js +3 -3
- package/lib-esm/ui/empty-set/empty-set.js.map +1 -1
- package/lib-esm/ui/hover-card/hover-card.js +1 -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 +1 -1
- package/lib-esm/ui/tooltip/tooltip.js.map +1 -1
- package/lib-esm/ui/tooltip/tooltip.module.css +11 -0
- package/package.json +26 -15
- package/src/app/app.jsx +6 -1
- package/src/app/app.module.css +11 -1
- package/src/app/app.stories.tsx +2 -2
- package/src/components/asset-info/asset-info.stories.tsx +47 -39
- package/src/components/asset-name/asset-name.stories.tsx +1 -3
- package/src/components/asset-not-predictive/asset-not-predictive.stories.tsx +22 -15
- package/src/components/browsertime-table/browsertime-table.stories.tsx +45 -0
- package/src/components/bundle-assets-totals/bundle-assets-totals.stories.tsx +47 -0
- package/src/components/bundle-modules/bundle-modules.stories.tsx +191 -0
- package/src/components/bundle-modules/bundle-modules.tsx +1 -1
- package/src/components/bundle-modules/index.tsx +4 -0
- package/src/components/bundle-packages/bundle-packages.stories.tsx +87 -0
- package/src/components/delta/delta.module.css +13 -12
- package/src/components/delta/delta.stories.tsx +57 -0
- package/src/components/delta/delta.tsx +32 -0
- package/src/components/entry-info/entry-info.stories.tsx +49 -54
- package/src/components/{index.js → index.ts} +7 -2
- package/src/components/insight-icon/insight-icon.module.css +6 -6
- package/src/components/insights/insights.stories.tsx +36 -33
- package/src/components/job-name/job-name.jsx +2 -3
- package/src/components/job-name/job-name.stories.tsx +46 -0
- package/src/components/jobs-header/jobs-header.stories.tsx +19 -15
- package/src/components/lighthouse-table/lighthouse-table.stories.tsx +30 -0
- package/src/components/metric/metric.stories.tsx +24 -22
- package/src/components/metric-change-legend/index.ts +1 -0
- package/src/components/metric-change-legend/metric-change-legend.module.css +69 -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.stories.tsx +45 -41
- package/src/components/metric-run-info/metric-run-info.tsx +41 -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/metrics-table.stories.tsx +33 -13
- package/src/components/metrics-table/metrics-table.tsx +1 -1
- package/src/components/metrics-table-header/metrics-table-header.module.css +8 -12
- package/src/components/metrics-table-header/metrics-table-header.tsx +14 -10
- package/src/components/metrics-table-options/metrics-table-options.tsx +1 -1
- package/src/components/metrics-table-title/metrics-table-title.jsx +1 -1
- package/src/components/module-info/module-info.stories.tsx +41 -30
- package/src/components/package-info/package-info.stories.tsx +20 -15
- package/src/components/run-info/run-info.module.css +35 -26
- package/src/components/run-info/run-info.stories.tsx +47 -39
- package/src/components/run-info/run-info.tsx +132 -73
- package/src/components/summary/summary.module.css +60 -10
- package/src/components/summary/summary.stories.tsx +26 -32
- package/src/components/summary/summary.tsx +47 -50
- package/src/constants.ts +13 -0
- package/src/css/default.css +1 -1
- package/src/css/variables.css +71 -58
- package/src/hooks/rows-sort.ts +9 -6
- package/src/layout/box/box.stories.tsx +35 -28
- package/src/layout/flex-stack/flex-stack.stories.tsx +79 -48
- package/src/layout/footer/footer.stories.tsx +30 -0
- package/src/layout/stack/stack.stories.tsx +68 -44
- package/src/ui/alert/alert.stories.tsx +25 -21
- package/src/ui/button/button.stories.tsx +181 -176
- package/src/ui/button/button.tsx +8 -1
- package/src/ui/container/container.stories.tsx +28 -21
- package/src/ui/control-group/control-group.stories.tsx +23 -16
- package/src/ui/dialog/dialog.module.css +22 -0
- package/src/ui/dialog/dialog.tsx +9 -2
- package/src/ui/dropdown/dropdown.module.css +11 -0
- package/src/ui/dropdown/dropdown.stories.tsx +23 -15
- package/src/ui/dropdown/dropdown.tsx +5 -1
- package/src/ui/empty-set/empty-set.jsx +16 -4
- package/src/ui/empty-set/empty-set.stories.tsx +41 -0
- package/src/ui/file-name/file-name.stories.tsx +45 -0
- package/src/ui/filters/filters.stories.tsx +29 -26
- package/src/ui/hover-card/hover-card.module.css +14 -0
- package/src/ui/hover-card/hover-card.stories.tsx +35 -26
- package/src/ui/hover-card/hover-card.tsx +1 -1
- package/src/ui/icon/icon.stories.tsx +36 -28
- package/src/ui/input/input.stories.tsx +17 -5
- package/src/ui/input-search/input-search.stories.tsx +31 -0
- package/src/ui/loader/loader.stories.tsx +22 -0
- package/src/ui/skeleton/skeleton.stories.tsx +42 -0
- package/src/ui/table/table.module.css +0 -1
- package/src/ui/table/table.stories.tsx +244 -218
- package/src/ui/tag/tag.stories.tsx +11 -10
- package/src/ui/toolbar/toolbar.stories.tsx +41 -0
- package/src/ui/tooltip/tooltip.module.css +11 -0
- package/src/ui/tooltip/tooltip.tsx +1 -1
- package/types/components/bundle-modules/bundle-modules.d.ts +1 -1
- package/types/components/bundle-modules/index.d.ts +2 -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 +25 -20
- 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 +2 -6
- package/types/components/metrics-table/metrics-table.d.ts +1 -1
- package/types/components/metrics-table-header/metrics-table-header.d.ts +1 -1
- package/types/components/run-info/run-info.d.ts +16 -7
- package/types/constants.d.ts +12 -0
- package/types/hooks/rows-sort.d.ts +2 -2
- package/types/ui/button/button.d.ts +1 -1
- package/types/ui/dialog/dialog.d.ts +3 -2
- package/types/ui/dropdown/dropdown.d.ts +1 -0
- package/vitest.config.ts +47 -0
- package/vitest.setup.ts +26 -0
- package/lib/assets/icons.svg.js +0 -100
- package/lib/assets/icons.svg.js.map +0 -1
- package/lib-esm/assets/icons.svg.js +0 -63
- package/lib-esm/assets/icons.svg.js.map +0 -1
- package/src/assets/icons.svg.jsx +0 -279
- package/src/components/delta/delta.jsx +0 -22
- package/types/assets/icons.svg.d.ts +0 -2
- /package/src/components/delta/{index.js → index.ts} +0 -0
|
@@ -1,53 +1,56 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { InsightType } from '@bundle-stats/utils';
|
|
2
3
|
|
|
3
4
|
import { getWrapperDecorator } from '../../stories';
|
|
4
5
|
import { Insights } from '.';
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
const meta = {
|
|
7
8
|
title: 'Components/Insights',
|
|
8
9
|
component: Insights,
|
|
9
10
|
decorators: [getWrapperDecorator()],
|
|
10
|
-
}
|
|
11
|
+
} satisfies Meta<typeof Insights>;
|
|
11
12
|
|
|
12
|
-
|
|
13
|
+
export default meta;
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
type Story = StoryObj<typeof meta>;
|
|
15
16
|
|
|
16
|
-
Default
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
export const Default: Story = {
|
|
18
|
+
args: {
|
|
19
|
+
insights: {
|
|
20
|
+
duplicatePackages: {
|
|
21
|
+
type: InsightType.ERROR,
|
|
22
|
+
data: {
|
|
23
|
+
packages: { 'package-a': ['package-a', 'package-a~1'] },
|
|
24
|
+
text: 'Bundle introduced 1 and removed 2 duplicate packages',
|
|
25
|
+
},
|
|
23
26
|
},
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
newPackages: {
|
|
28
|
+
type: InsightType.WARNING,
|
|
29
|
+
data: {
|
|
30
|
+
text: 'Bundle introduced 2 new packages: package-c, package-d',
|
|
31
|
+
packages: ['package-c', 'package-d'],
|
|
32
|
+
},
|
|
30
33
|
},
|
|
31
34
|
},
|
|
32
35
|
},
|
|
33
36
|
};
|
|
34
37
|
|
|
35
|
-
export const Info =
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
export const Info: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
insights: {
|
|
41
|
+
duplicatePackages: {
|
|
42
|
+
type: InsightType.INFO,
|
|
43
|
+
data: {
|
|
44
|
+
packages: { 'package-a': ['package-a', 'package-a~1'] },
|
|
45
|
+
text: 'Bundle removed 1 duplicate packages',
|
|
46
|
+
},
|
|
44
47
|
},
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
newPackages: {
|
|
49
|
+
type: InsightType.WARNING,
|
|
50
|
+
data: {
|
|
51
|
+
text: 'Bundle introduced 2 new packages: package-c, package-d',
|
|
52
|
+
packages: ['package-c', 'package-d'],
|
|
53
|
+
},
|
|
51
54
|
},
|
|
52
55
|
},
|
|
53
56
|
},
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
|
|
4
|
-
import { Tooltip } from '../../ui/tooltip';
|
|
5
4
|
import css from './job-name.module.css';
|
|
6
5
|
|
|
7
6
|
export const JobName = ({
|
|
@@ -11,9 +10,9 @@ export const JobName = ({
|
|
|
11
10
|
children,
|
|
12
11
|
...restProps
|
|
13
12
|
}) => (
|
|
14
|
-
<
|
|
13
|
+
<Component className={css.root} title={title} {...restProps}>
|
|
15
14
|
{children || `Job #${internalBuildNumber}`}
|
|
16
|
-
</
|
|
15
|
+
</Component>
|
|
17
16
|
);
|
|
18
17
|
|
|
19
18
|
JobName.defaultProps = {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
|
|
4
|
+
import { getWrapperDecorator } from '../../stories';
|
|
5
|
+
import { JobName } from '.';
|
|
6
|
+
|
|
7
|
+
// JobName is a plain .jsx component with defaultProps instead of inline
|
|
8
|
+
// destructuring defaults, so TS can't infer its props as optional on its own.
|
|
9
|
+
const TypedJobName = JobName as unknown as React.ComponentType<{
|
|
10
|
+
as?: React.ElementType;
|
|
11
|
+
title?: string;
|
|
12
|
+
internalBuildNumber?: number;
|
|
13
|
+
children?: React.ReactNode;
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
const meta = {
|
|
17
|
+
title: 'Components/JobName',
|
|
18
|
+
component: TypedJobName,
|
|
19
|
+
decorators: [getWrapperDecorator({ padding: '64px' })],
|
|
20
|
+
args: {
|
|
21
|
+
title: 'View job details',
|
|
22
|
+
},
|
|
23
|
+
} satisfies Meta<typeof TypedJobName>;
|
|
24
|
+
|
|
25
|
+
export default meta;
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
args: {
|
|
31
|
+
internalBuildNumber: 10,
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const CustomComponent: Story = {
|
|
36
|
+
args: {
|
|
37
|
+
internalBuildNumber: 10,
|
|
38
|
+
as: 'strong',
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const Render: Story = {
|
|
43
|
+
args: {
|
|
44
|
+
children: <a href="https://relative-ci.com/test">#10</a>,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
2
|
|
|
3
3
|
import { getWrapperDecorator } from '../../stories';
|
|
4
4
|
import { JobsHeader } from '.';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const meta = {
|
|
7
7
|
title: 'Components/JobsHeader',
|
|
8
8
|
component: JobsHeader,
|
|
9
9
|
decorators: [getWrapperDecorator()],
|
|
10
|
-
}
|
|
10
|
+
} satisfies Meta<typeof JobsHeader>;
|
|
11
|
+
|
|
12
|
+
export default meta;
|
|
13
|
+
|
|
14
|
+
type Story = StoryObj<typeof meta>;
|
|
11
15
|
|
|
12
|
-
export const Default =
|
|
13
|
-
|
|
14
|
-
jobs
|
|
16
|
+
export const Default: Story = {
|
|
17
|
+
args: {
|
|
18
|
+
jobs: [
|
|
15
19
|
{
|
|
16
20
|
internalBuildNumber: 1,
|
|
17
21
|
meta: {
|
|
@@ -21,13 +25,13 @@ export const Default = () => (
|
|
|
21
25
|
},
|
|
22
26
|
},
|
|
23
27
|
},
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
27
31
|
|
|
28
|
-
export const MultipleJobs =
|
|
29
|
-
|
|
30
|
-
jobs
|
|
32
|
+
export const MultipleJobs: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
jobs: [
|
|
31
35
|
{
|
|
32
36
|
internalBuildNumber: 1,
|
|
33
37
|
meta: {
|
|
@@ -46,6 +50,6 @@ export const MultipleJobs = () => (
|
|
|
46
50
|
},
|
|
47
51
|
},
|
|
48
52
|
},
|
|
49
|
-
]
|
|
50
|
-
|
|
51
|
-
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { createJobs } from '@bundle-stats/utils';
|
|
3
|
+
|
|
4
|
+
import lighthouse from '../../../__mocks__/lighthouse.json';
|
|
5
|
+
import { getWrapperDecorator } from '../../stories';
|
|
6
|
+
import { LighthouseTable } from '.';
|
|
7
|
+
|
|
8
|
+
const JOBS = createJobs([{ lighthouse }, { lighthouse }]);
|
|
9
|
+
|
|
10
|
+
const meta = {
|
|
11
|
+
title: 'Components/LighthouseTable',
|
|
12
|
+
component: LighthouseTable,
|
|
13
|
+
decorators: [getWrapperDecorator()],
|
|
14
|
+
} satisfies Meta<typeof LighthouseTable>;
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
|
|
18
|
+
type Story = StoryObj<typeof meta>;
|
|
19
|
+
|
|
20
|
+
export const Default: Story = {
|
|
21
|
+
args: {
|
|
22
|
+
jobs: JOBS,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const NoBaseline: Story = {
|
|
27
|
+
args: {
|
|
28
|
+
jobs: [JOBS[1]],
|
|
29
|
+
},
|
|
30
|
+
};
|
|
@@ -1,41 +1,43 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Meta,
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
3
|
|
|
4
4
|
import { getWrapperDecorator } from '../../stories';
|
|
5
5
|
import { Delta } from '../delta';
|
|
6
6
|
import { Metric } from '.';
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const meta = {
|
|
9
9
|
title: 'Components/Metric',
|
|
10
10
|
component: Metric,
|
|
11
11
|
decorators: [getWrapperDecorator({ maxWidth: '200px' })],
|
|
12
|
-
}
|
|
12
|
+
} satisfies Meta<typeof Metric>;
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
export default meta;
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
type Story = StoryObj<typeof meta>;
|
|
17
17
|
|
|
18
|
-
Default
|
|
19
|
-
|
|
18
|
+
export const Default: Story = {
|
|
19
|
+
args: {
|
|
20
|
+
value: '100',
|
|
21
|
+
},
|
|
20
22
|
};
|
|
21
23
|
|
|
22
|
-
export const WithUnit =
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
export const WithUnit: Story = {
|
|
25
|
+
args: {
|
|
26
|
+
value: '100',
|
|
27
|
+
unit: 'KiB',
|
|
28
|
+
},
|
|
27
29
|
};
|
|
28
30
|
|
|
29
|
-
export const WithDelta =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
export const WithDelta: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
...WithUnit.args,
|
|
34
|
+
children: <Delta displayValue="+10%" deltaType="POSITIVE" />,
|
|
35
|
+
},
|
|
34
36
|
};
|
|
35
37
|
|
|
36
|
-
export const Inline =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
export const Inline: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
...WithDelta.args,
|
|
41
|
+
inline: true,
|
|
42
|
+
},
|
|
41
43
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './metric-change-legend';
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
.root {
|
|
2
|
+
font-size: var(--size-small);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.itemAnchor {
|
|
6
|
+
color: var(--color-text-light);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.itemAnchor:hover {
|
|
10
|
+
color: var(--color-text);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.variants {
|
|
14
|
+
display: flex;
|
|
15
|
+
gap: 1px;
|
|
16
|
+
overflow: hidden;
|
|
17
|
+
border-radius: var(--radius-xsmall);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
.infoPreviewCell {
|
|
21
|
+
width: 1%;
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.infoDescriptionCell {
|
|
26
|
+
padding-left: 0 !important;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.variant {
|
|
30
|
+
width: var(--space-xxsmall);
|
|
31
|
+
height: var(--space-xxsmall);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.large .variant {
|
|
35
|
+
width: var(--space-small);
|
|
36
|
+
height: var(--space-small);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.bar-improvement .variant-low {
|
|
40
|
+
background: var(--color-green-light);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.bar-improvement .variant-medium {
|
|
44
|
+
background: var(--color-green);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.bar-improvement .variant-high {
|
|
48
|
+
background: var(--color-green-dark);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.bar-regression .variant-low {
|
|
52
|
+
background: var(--color-red-light);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.bar-regression .variant-medium {
|
|
56
|
+
background: var(--color-red);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.bar-regression .variant-high {
|
|
60
|
+
background: var(--color-red-dark);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.bar-neutral .variant-medium {
|
|
64
|
+
background: var(--color-info);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.bar-no-change .variant-medium {
|
|
68
|
+
background: var(--color-gray-ultra-light);
|
|
69
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
|
|
3
|
+
import { MetricChangeLegend } from '.';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/MetricChangeLegend',
|
|
7
|
+
component: MetricChangeLegend,
|
|
8
|
+
} satisfies Meta<typeof MetricChangeLegend>;
|
|
9
|
+
|
|
10
|
+
export default meta;
|
|
11
|
+
type Story = StoryObj<typeof meta>;
|
|
12
|
+
|
|
13
|
+
export const Default: Story = {};
|
|
@@ -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} />
|
|
139
|
+
<span>{label}</span>
|
|
140
|
+
</FlexStack>
|
|
141
|
+
}
|
|
142
|
+
>
|
|
143
|
+
{info}
|
|
144
|
+
</HoverCard>
|
|
145
|
+
))}
|
|
146
|
+
</FlexStack>
|
|
147
|
+
);
|
|
148
|
+
};
|
|
@@ -1,61 +1,65 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
3
|
|
|
3
|
-
import { Meta, Story } from '@storybook/react';
|
|
4
4
|
import { MetricRunInfo } from '.';
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
const meta = {
|
|
7
7
|
title: 'Components/MetricRunInfo',
|
|
8
8
|
component: MetricRunInfo,
|
|
9
|
-
}
|
|
9
|
+
} satisfies Meta<typeof MetricRunInfo>;
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
export default meta;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
14
|
|
|
15
|
-
Default
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
args: {
|
|
17
|
+
metricId: 'webpack.totalSizeByTypeALL',
|
|
18
|
+
current: 120 * 1024,
|
|
19
|
+
baseline: 100 * 1024,
|
|
20
|
+
},
|
|
19
21
|
};
|
|
20
22
|
|
|
21
|
-
export const NoBaseline =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
export const NoBaseline: Story = {
|
|
24
|
+
args: {
|
|
25
|
+
metricId: 'webpack.totalSizeByTypeALL',
|
|
26
|
+
current: 120 * 1024,
|
|
27
|
+
showBaseline: false,
|
|
28
|
+
},
|
|
27
29
|
};
|
|
28
30
|
|
|
29
|
-
export const NoDelta =
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
31
|
+
export const NoDelta: Story = {
|
|
32
|
+
args: {
|
|
33
|
+
...NoBaseline.args,
|
|
34
|
+
showDelta: false,
|
|
35
|
+
},
|
|
34
36
|
};
|
|
35
37
|
|
|
36
|
-
export const MetricNoDelta =
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
export const MetricNoDelta: Story = {
|
|
39
|
+
args: {
|
|
40
|
+
metricId: 'webpack.cacheInvalidation',
|
|
41
|
+
current: 85,
|
|
42
|
+
baseline: 50,
|
|
43
|
+
},
|
|
42
44
|
};
|
|
43
45
|
|
|
44
|
-
export const CustomTitle =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
46
|
+
export const CustomTitle: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
...Default.args,
|
|
49
|
+
titleWrapper: ({ children, style, ...restProps }) => (
|
|
50
|
+
<h1 style={{ ...style, fontStyle: 'italic' }} {...restProps}>
|
|
51
|
+
{children}
|
|
52
|
+
</h1>
|
|
53
|
+
),
|
|
54
|
+
},
|
|
53
55
|
};
|
|
54
56
|
|
|
55
|
-
export const CustomComponent =
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
57
|
+
export const CustomComponent: Story = {
|
|
58
|
+
// MetricRunInfoProps only types its passthrough props as ComponentProps<'div'>,
|
|
59
|
+
// but they're forwarded to RunInfo, which supports polymorphic `as` at runtime.
|
|
60
|
+
args: {
|
|
61
|
+
...Default.args,
|
|
62
|
+
as: 'a',
|
|
63
|
+
href: 'https://google.com/search?query=bundle+stats',
|
|
64
|
+
} as unknown as Story['args'],
|
|
61
65
|
};
|