@bundle-stats/ui 3.3.0-alpha.0 → 3.3.0

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.
Files changed (237) hide show
  1. package/CHANGELOG.md +74 -11
  2. package/lib/app/app.js +124 -104
  3. package/lib/app/app.module.css +11 -4
  4. package/lib/app/app.stories.js +1 -22
  5. package/lib/app/header/header.js +1 -10
  6. package/lib/assets/icons.svg +0 -8
  7. package/lib/components/asset-info/asset-info.module.css +1 -0
  8. package/lib/components/bundle-assets/bundle-assets.js +104 -52
  9. package/lib/components/bundle-assets/bundle-assets.module.css +24 -26
  10. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.js +16 -43
  11. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  12. package/lib/components/bundle-assets-totals-table/bundle-assets-totals-table.stories.js +1 -20
  13. package/lib/components/bundle-modules/bundle-modules.js +68 -68
  14. package/lib/components/bundle-modules/bundle-modules.module.css +11 -2
  15. package/lib/components/bundle-modules/bundle-modules.utils.js +14 -10
  16. package/lib/components/bundle-modules/index.js +4 -4
  17. package/lib/components/bundle-packages/bundle-packages.js +100 -44
  18. package/lib/components/bundle-packages/bundle-packages.module.css +17 -21
  19. package/lib/components/delta/delta.module.css +1 -0
  20. package/lib/components/job-header/job-header.js +3 -1
  21. package/lib/components/job-header/job-header.module.css +6 -8
  22. package/lib/components/jobs-header/jobs-header.module.css +5 -0
  23. package/lib/components/metrics-table/metrics-table.js +72 -59
  24. package/lib/components/metrics-table/metrics-table.module.css +18 -7
  25. package/lib/components/metrics-table-search/metrics-table-search.module.css +5 -4
  26. package/lib/components/metrics-table-title/metrics-table-title.js +9 -7
  27. package/lib/components/metrics-table-title/metrics-table-title.module.css +2 -0
  28. package/lib/components/module-info/module-info.js +2 -2
  29. package/lib/components/module-info/module-info.module.css +1 -0
  30. package/lib/components/summary/summary.js +7 -12
  31. package/lib/components/summary/summary.module.css +1 -1
  32. package/lib/components/summary/summary.stories.js +0 -29
  33. package/lib/components/summary-item/summary-item.js +18 -38
  34. package/lib/components/summary-item/summary-item.module.css +1 -34
  35. package/lib/components/summary-item/summary-item.stories.js +53 -51
  36. package/lib/components/total-size-type-title/total-size-type-title.js +7 -3
  37. package/lib/constants.js +4 -4
  38. package/lib/css/default.css +14 -3
  39. package/lib/css/variables.css +17 -17
  40. package/lib/hooks/search-params.js +31 -31
  41. package/lib/layout/box/box.module.css +9 -0
  42. package/lib/layout/footer/footer.module.css +1 -1
  43. package/lib/layout/index.js +8 -0
  44. package/lib/layout/separator.js +48 -0
  45. package/lib/layout/separator.module.css +5 -0
  46. package/lib/ui/alert/alert.js +3 -13
  47. package/lib/ui/dropdown/dropdown.js +21 -26
  48. package/lib/ui/dropdown/dropdown.module.css +11 -12
  49. package/lib/ui/dropdown/dropdown.stories.js +2 -9
  50. package/lib/ui/empty-set/empty-set.js +5 -4
  51. package/lib/ui/empty-set/empty-set.module.css +2 -2
  52. package/lib/ui/filters/filters.container.js +1 -1
  53. package/lib/ui/filters/filters.js +22 -7
  54. package/lib/ui/filters/filters.module.css +3 -3
  55. package/lib/ui/horizontal-bar-chart/horizontal-bar-chart.js +1 -1
  56. package/lib/ui/hover-card/hover-card.js +102 -0
  57. package/lib/ui/hover-card/hover-card.module.css +29 -0
  58. package/lib/ui/hover-card/hover-card.stories.js +56 -0
  59. package/lib/{components/budget-info → ui/hover-card}/index.js +4 -4
  60. package/lib/ui/icon/icon.js +6 -8
  61. package/lib/ui/icon/icon.module.css +1 -0
  62. package/lib/ui/index.js +8 -8
  63. package/lib/ui/table/table.js +5 -74
  64. package/lib/ui/table/table.module.css +41 -25
  65. package/lib/ui/table/table.stories.js +1 -1
  66. package/lib/ui/{popover → tag}/index.js +4 -4
  67. package/lib/ui/tag/tag.js +72 -0
  68. package/lib/ui/tag/tag.module.css +55 -0
  69. package/lib/ui/tag/tag.stories.js +38 -0
  70. package/lib/ui/tooltip/tooltip.js +10 -9
  71. package/lib/ui/tooltip/tooltip.module.css +2 -1
  72. package/lib-esm/app/app.js +119 -103
  73. package/lib-esm/app/app.module.css +11 -4
  74. package/lib-esm/app/app.stories.js +1 -22
  75. package/lib-esm/app/header/header.js +1 -9
  76. package/lib-esm/assets/icons.svg +0 -8
  77. package/lib-esm/components/asset-info/asset-info.module.css +1 -0
  78. package/lib-esm/components/bundle-assets/bundle-assets.js +97 -56
  79. package/lib-esm/components/bundle-assets/bundle-assets.module.css +24 -26
  80. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.js +13 -27
  81. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  82. package/lib-esm/components/bundle-assets-totals-table/bundle-assets-totals-table.stories.js +0 -18
  83. package/lib-esm/components/bundle-modules/bundle-modules.js +50 -51
  84. package/lib-esm/components/bundle-modules/bundle-modules.module.css +11 -2
  85. package/lib-esm/components/bundle-modules/bundle-modules.utils.js +14 -6
  86. package/lib-esm/components/bundle-modules/index.js +5 -3
  87. package/lib-esm/components/bundle-packages/bundle-packages.js +88 -41
  88. package/lib-esm/components/bundle-packages/bundle-packages.module.css +17 -21
  89. package/lib-esm/components/delta/delta.module.css +1 -0
  90. package/lib-esm/components/job-header/job-header.js +2 -1
  91. package/lib-esm/components/job-header/job-header.module.css +6 -8
  92. package/lib-esm/components/jobs-header/jobs-header.module.css +5 -0
  93. package/lib-esm/components/metrics-table/metrics-table.js +61 -53
  94. package/lib-esm/components/metrics-table/metrics-table.module.css +18 -7
  95. package/lib-esm/components/metrics-table-search/metrics-table-search.module.css +5 -4
  96. package/lib-esm/components/metrics-table-title/metrics-table-title.js +8 -7
  97. package/lib-esm/components/metrics-table-title/metrics-table-title.module.css +2 -0
  98. package/lib-esm/components/module-info/module-info.js +2 -2
  99. package/lib-esm/components/module-info/module-info.module.css +1 -0
  100. package/lib-esm/components/summary/summary.js +7 -11
  101. package/lib-esm/components/summary/summary.module.css +1 -1
  102. package/lib-esm/components/summary/summary.stories.js +0 -27
  103. package/lib-esm/components/summary-item/summary-item.js +16 -36
  104. package/lib-esm/components/summary-item/summary-item.module.css +1 -34
  105. package/lib-esm/components/summary-item/summary-item.stories.js +38 -50
  106. package/lib-esm/components/total-size-type-title/total-size-type-title.js +6 -3
  107. package/lib-esm/constants.js +4 -4
  108. package/lib-esm/css/default.css +14 -3
  109. package/lib-esm/css/variables.css +17 -17
  110. package/lib-esm/hooks/search-params.js +27 -28
  111. package/lib-esm/layout/box/box.module.css +9 -0
  112. package/lib-esm/layout/footer/footer.module.css +1 -1
  113. package/lib-esm/layout/index.js +1 -0
  114. package/lib-esm/layout/separator.js +28 -0
  115. package/lib-esm/layout/separator.module.css +5 -0
  116. package/lib-esm/ui/alert/alert.js +3 -6
  117. package/lib-esm/ui/dropdown/dropdown.js +20 -25
  118. package/lib-esm/ui/dropdown/dropdown.module.css +11 -12
  119. package/lib-esm/ui/dropdown/dropdown.stories.js +2 -7
  120. package/lib-esm/ui/empty-set/empty-set.js +4 -4
  121. package/lib-esm/ui/empty-set/empty-set.module.css +2 -2
  122. package/lib-esm/ui/filters/filters.js +20 -5
  123. package/lib-esm/ui/filters/filters.module.css +3 -3
  124. package/lib-esm/ui/hover-card/hover-card.js +83 -0
  125. package/lib-esm/ui/hover-card/hover-card.module.css +29 -0
  126. package/lib-esm/ui/hover-card/hover-card.stories.js +35 -0
  127. package/lib-esm/ui/hover-card/index.js +1 -0
  128. package/lib-esm/ui/icon/icon.js +3 -5
  129. package/lib-esm/ui/icon/icon.module.css +1 -0
  130. package/lib-esm/ui/index.js +1 -1
  131. package/lib-esm/ui/table/table.js +5 -65
  132. package/lib-esm/ui/table/table.module.css +41 -25
  133. package/lib-esm/ui/table/table.stories.js +1 -1
  134. package/lib-esm/ui/tag/index.js +1 -0
  135. package/lib-esm/ui/tag/tag.js +45 -0
  136. package/lib-esm/ui/tag/tag.module.css +55 -0
  137. package/lib-esm/ui/tag/tag.stories.js +23 -0
  138. package/lib-esm/ui/tooltip/tooltip.js +10 -9
  139. package/lib-esm/ui/tooltip/tooltip.module.css +2 -1
  140. package/package.json +33 -31
  141. package/src/app/app.jsx +135 -145
  142. package/src/app/app.module.css +11 -4
  143. package/src/app/header/header.jsx +0 -10
  144. package/src/assets/icons.svg +0 -8
  145. package/src/components/asset-info/asset-info.module.css +1 -0
  146. package/src/components/bundle-assets/bundle-assets.jsx +85 -31
  147. package/src/components/bundle-assets/bundle-assets.module.css +24 -26
  148. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.jsx +13 -26
  149. package/src/components/bundle-assets-totals-table/bundle-assets-totals-table.module.css +2 -2
  150. package/src/components/bundle-modules/bundle-modules.jsx +53 -36
  151. package/src/components/bundle-modules/bundle-modules.module.css +11 -2
  152. package/src/components/bundle-modules/bundle-modules.utils.js +16 -4
  153. package/src/components/bundle-modules/index.jsx +3 -0
  154. package/src/components/bundle-packages/bundle-packages.jsx +89 -39
  155. package/src/components/bundle-packages/bundle-packages.module.css +17 -21
  156. package/src/components/delta/delta.module.css +1 -0
  157. package/src/components/job-header/job-header.jsx +2 -1
  158. package/src/components/job-header/job-header.module.css +6 -8
  159. package/src/components/jobs-header/jobs-header.module.css +5 -0
  160. package/src/components/metrics-table/metrics-table.jsx +53 -44
  161. package/src/components/metrics-table/metrics-table.module.css +18 -7
  162. package/src/components/metrics-table-search/metrics-table-search.module.css +5 -4
  163. package/src/components/metrics-table-title/metrics-table-title.jsx +20 -21
  164. package/src/components/metrics-table-title/metrics-table-title.module.css +2 -0
  165. package/src/components/module-info/module-info.jsx +3 -7
  166. package/src/components/module-info/module-info.module.css +1 -0
  167. package/src/components/summary/summary.jsx +7 -8
  168. package/src/components/summary/summary.module.css +1 -1
  169. package/src/components/summary-item/summary-item.jsx +23 -40
  170. package/src/components/summary-item/summary-item.module.css +1 -34
  171. package/src/components/total-size-type-title/total-size-type-title.jsx +6 -9
  172. package/src/constants.js +11 -7
  173. package/src/css/default.css +14 -3
  174. package/src/css/variables.css +17 -17
  175. package/src/hooks/search-params.js +42 -33
  176. package/src/layout/box/box.module.css +9 -0
  177. package/src/layout/footer/footer.module.css +1 -1
  178. package/src/layout/index.js +1 -0
  179. package/src/layout/separator.jsx +25 -0
  180. package/src/layout/separator.module.css +5 -0
  181. package/src/ui/alert/alert.jsx +2 -7
  182. package/src/ui/dropdown/dropdown.jsx +16 -22
  183. package/src/ui/dropdown/dropdown.module.css +11 -12
  184. package/src/ui/empty-set/empty-set.jsx +25 -21
  185. package/src/ui/empty-set/empty-set.module.css +2 -2
  186. package/src/ui/filters/filters.jsx +64 -53
  187. package/src/ui/filters/filters.module.css +3 -3
  188. package/src/ui/hover-card/hover-card.jsx +73 -0
  189. package/src/ui/hover-card/hover-card.module.css +29 -0
  190. package/src/ui/hover-card/index.js +1 -0
  191. package/src/ui/icon/icon.jsx +11 -9
  192. package/src/ui/icon/icon.module.css +1 -0
  193. package/src/ui/index.js +1 -1
  194. package/src/ui/table/table.jsx +5 -52
  195. package/src/ui/table/table.module.css +41 -25
  196. package/src/ui/tag/index.js +1 -0
  197. package/src/ui/tag/tag.jsx +49 -0
  198. package/src/ui/tag/tag.module.css +55 -0
  199. package/src/ui/tooltip/tooltip.jsx +10 -14
  200. package/src/ui/tooltip/tooltip.module.css +2 -1
  201. package/lib/assets/icons/alert-circle.svg +0 -1
  202. package/lib/assets/icons/check-circle.svg +0 -1
  203. package/lib/components/budget-info/budget-info.js +0 -53
  204. package/lib/components/budget-info/budget-info.module.css +0 -28
  205. package/lib/components/budget-info/budget-info.stories.js +0 -42
  206. package/lib/components/budget-insights/budget-insights.js +0 -200
  207. package/lib/components/budget-insights/budget-insights.module.css +0 -53
  208. package/lib/components/budget-insights/budget-insights.stories.js +0 -104
  209. package/lib/components/budget-insights/index.js +0 -18
  210. package/lib/ui/popover/popover.js +0 -92
  211. package/lib/ui/popover/popover.module.css +0 -66
  212. package/lib/ui/popover/popover.stories.js +0 -26
  213. package/lib-esm/assets/icons/alert-circle.svg +0 -1
  214. package/lib-esm/assets/icons/check-circle.svg +0 -1
  215. package/lib-esm/components/budget-info/budget-info.js +0 -37
  216. package/lib-esm/components/budget-info/budget-info.module.css +0 -28
  217. package/lib-esm/components/budget-info/budget-info.stories.js +0 -26
  218. package/lib-esm/components/budget-info/index.js +0 -1
  219. package/lib-esm/components/budget-insights/budget-insights.js +0 -147
  220. package/lib-esm/components/budget-insights/budget-insights.module.css +0 -53
  221. package/lib-esm/components/budget-insights/budget-insights.stories.js +0 -84
  222. package/lib-esm/components/budget-insights/index.js +0 -1
  223. package/lib-esm/ui/popover/index.js +0 -1
  224. package/lib-esm/ui/popover/popover.js +0 -71
  225. package/lib-esm/ui/popover/popover.module.css +0 -66
  226. package/lib-esm/ui/popover/popover.stories.js +0 -14
  227. package/src/assets/icons/alert-circle.svg +0 -1
  228. package/src/assets/icons/check-circle.svg +0 -1
  229. package/src/components/budget-info/budget-info.jsx +0 -49
  230. package/src/components/budget-info/budget-info.module.css +0 -28
  231. package/src/components/budget-info/index.js +0 -1
  232. package/src/components/budget-insights/budget-insights.jsx +0 -152
  233. package/src/components/budget-insights/budget-insights.module.css +0 -53
  234. package/src/components/budget-insights/index.js +0 -1
  235. package/src/ui/popover/index.js +0 -1
  236. package/src/ui/popover/popover.jsx +0 -79
  237. package/src/ui/popover/popover.module.css +0 -66
package/src/app/app.jsx CHANGED
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo } from 'react';
1
+ import React, { useContext, useEffect, useMemo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { HashRouter, NavLink, Route, Switch, useLocation } from 'react-router-dom';
4
4
  import { COMPONENT } from '@bundle-stats/utils';
@@ -13,7 +13,6 @@ import {
13
13
  import { Box } from '../layout/box';
14
14
  import { Container } from '../ui/container';
15
15
  import { DuplicatePackagesWarning } from '../components/duplicate-packages-warning';
16
- import { BudgetInsights } from '../components/budget-insights';
17
16
  import { Summary } from '../components/summary';
18
17
  import { BundleAssets } from '../components/bundle-assets';
19
18
  import { BundleAssetsTotalsChartBars } from '../components/bundle-assets-totals-chart-bars';
@@ -57,16 +56,110 @@ Layout.defaultProps = {
57
56
  version: null,
58
57
  };
59
58
 
60
- const AppComponent = ({ version, jobs }) => {
59
+ const JobsContext = React.createContext({ jobs: [] });
60
+ const JobsProvider = ({ jobs, ...restProps }) => {
61
+ const value = useMemo(() => ({ jobs }), [jobs]);
62
+ return <JobsContext.Provider value={value} {...restProps} />;
63
+ };
64
+
65
+ JobsProvider.propTypes = {
66
+ jobs: PropTypes.arrayOf(PropTypes.object).isRequired,
67
+ };
68
+
69
+ const OverviewContent = () => {
70
+ const { jobs } = useContext(JobsContext);
71
+ const { duplicatePackagesCount } = jobs[0].summary.webpack;
72
+ const duplicatePackagesInsights = Boolean(
73
+ duplicatePackagesCount.current || duplicatePackagesCount.baseline,
74
+ );
75
+
76
+ return (
77
+ <Stack space="medium">
78
+ {duplicatePackagesInsights && (
79
+ <Container>
80
+ <DuplicatePackagesWarning
81
+ duplicatePackagesCount={duplicatePackagesCount}
82
+ showDelta={jobs.length > 1}
83
+ />
84
+ </Container>
85
+ )}
86
+ <Container>
87
+ <Stack space="small">
88
+ <TotalSizeTypeTitle />
89
+ <BundleAssetsTotalsChartBars jobs={jobs} />
90
+ <BundleAssetsTotalsTable jobs={jobs} outline />
91
+ </Stack>
92
+ </Container>
93
+ </Stack>
94
+ );
95
+ };
96
+
97
+ const AssetsContent = () => {
61
98
  const [bundleStatsState, bundleStatsSetState] = useComponentQueryState(COMPONENT.BUNDLE_ASSETS);
62
- const [bundlePackagesState, bundlePackagesSetState] = useComponentQueryState(
63
- COMPONENT.BUNDLE_PACKAGES,
99
+ const { jobs } = useContext(JobsContext);
100
+
101
+ return (
102
+ <Container>
103
+ <Stack space="medium">
104
+ <Summary
105
+ keys={METRICS_WEBPACK_ASSETS}
106
+ data={jobs?.[0]?.summary}
107
+ showSummaryItemDelta={jobs?.length !== 1}
108
+ />
109
+ <Box outline>
110
+ <BundleAssets jobs={jobs} setState={bundleStatsSetState} {...bundleStatsState} />
111
+ </Box>
112
+ </Stack>
113
+ </Container>
64
114
  );
115
+ };
116
+
117
+ const ModulesContent = () => {
65
118
  const [bundleModulesState, bundleModulesSetState] = useComponentQueryState(
66
119
  COMPONENT.BUNDLE_MODULES,
67
120
  );
121
+ const { jobs } = useContext(JobsContext);
68
122
 
69
- if (jobs.length === 0) {
123
+ return (
124
+ <Container>
125
+ <Stack space="medium">
126
+ <Summary
127
+ keys={METRICS_WEBPACK_MODULES}
128
+ data={jobs?.[0]?.summary}
129
+ showSummaryItemDelta={jobs?.length !== 1}
130
+ />
131
+ <Box outline>
132
+ <BundleModules jobs={jobs} setState={bundleModulesSetState} {...bundleModulesState} />
133
+ </Box>
134
+ </Stack>
135
+ </Container>
136
+ );
137
+ };
138
+
139
+ const PackagesContent = () => {
140
+ const [bundlePackagesState, bundlePackagesSetState] = useComponentQueryState(
141
+ COMPONENT.BUNDLE_PACKAGES,
142
+ );
143
+ const { jobs } = useContext(JobsContext);
144
+
145
+ return (
146
+ <Container>
147
+ <Stack space="medium">
148
+ <Summary
149
+ keys={METRICS_WEBPACK_PACKAGES}
150
+ data={jobs?.[0]?.summary}
151
+ showSummaryItemDelta={jobs?.length !== 1}
152
+ />
153
+ <Box outline>
154
+ <BundlePackages jobs={jobs} {...bundlePackagesState} setState={bundlePackagesSetState} />
155
+ </Box>
156
+ </Stack>
157
+ </Container>
158
+ );
159
+ };
160
+
161
+ const AppComponent = ({ version, jobs }) => {
162
+ if (jobs?.length === 0) {
70
163
  return (
71
164
  <Layout version={version}>
72
165
  <Container>
@@ -76,148 +169,45 @@ const AppComponent = ({ version, jobs }) => {
76
169
  );
77
170
  }
78
171
 
79
- const { summary, insights } = useMemo(() => jobs[0], jobs);
80
-
81
- const { duplicatePackagesCount } = summary.webpack;
82
- const duplicatePackagesInsights = Boolean(
83
- duplicatePackagesCount.current || duplicatePackagesCount.baseline,
84
- );
85
-
86
172
  return (
87
- <Layout jobs={jobs} version={version}>
88
- <Container className={css.summaryContainer}>
89
- <Summary
90
- size="large"
91
- keys={METRICS_WEBPACK_GENERAL}
92
- data={summary}
93
- budgets={insights?.webpack?.budgets}
94
- showSummaryItemDelta={jobs.length !== 1}
95
- />
96
- </Container>
173
+ <JobsProvider jobs={jobs}>
174
+ <Layout jobs={jobs} version={version}>
175
+ <Container className={css.summaryContainer}>
176
+ <Summary
177
+ size="large"
178
+ keys={METRICS_WEBPACK_GENERAL}
179
+ data={jobs[0].summary}
180
+ showSummaryItemDelta={jobs.length !== 1}
181
+ />
182
+ </Container>
97
183
 
98
- <Container className={css.tabsContainer}>
99
- <Tabs className={css.tabs}>
100
- <NavLink exact to={URLS.OVERVIEW} activeClassName={css.tabActive}>
101
- {I18N.OVERVIEW}
102
- </NavLink>
103
- <NavLink exact to={URLS.ASSETS} activeClassName={css.tabActive}>
104
- {I18N.ASSETS}
105
- </NavLink>
106
- <NavLink exact to={URLS.MODULES} activeClassName={css.tabActive}>
107
- {I18N.MODULES}
108
- </NavLink>
109
- <NavLink exact to={URLS.PACKAGES} activeClassName={css.tabActive}>
110
- {I18N.PACKAGES}
111
- </NavLink>
112
- </Tabs>
113
- </Container>
184
+ <Container className={css.tabsContainer}>
185
+ <Tabs className={css.tabs}>
186
+ <NavLink exact to={URLS.OVERVIEW} activeClassName={css.tabActive}>
187
+ {I18N.OVERVIEW}
188
+ </NavLink>
189
+ <NavLink exact to={URLS.ASSETS} activeClassName={css.tabActive}>
190
+ {I18N.ASSETS}
191
+ </NavLink>
192
+ <NavLink exact to={URLS.MODULES} activeClassName={css.tabActive}>
193
+ {I18N.MODULES}
194
+ </NavLink>
195
+ <NavLink exact to={URLS.PACKAGES} activeClassName={css.tabActive}>
196
+ {I18N.PACKAGES}
197
+ </NavLink>
198
+ </Tabs>
199
+ </Container>
114
200
 
115
- <div className={css.tabsContent}>
116
- <Switch>
117
- <Route
118
- exact
119
- path={URLS.ASSETS}
120
- render={({ location }) => (
121
- <Container>
122
- <Stack space="medium">
123
- <Summary
124
- keys={METRICS_WEBPACK_ASSETS}
125
- data={summary}
126
- budgets={insights?.webpack?.budgets}
127
- showSummaryItemDelta={jobs.length !== 1}
128
- />
129
- <Box outline>
130
- <BundleAssets
131
- jobs={jobs}
132
- setState={bundleStatsSetState}
133
- {...bundleStatsState}
134
- key={`${location.pathname}_${location.search}`}
135
- />
136
- </Box>
137
- </Stack>
138
- </Container>
139
- )}
140
- />
141
- <Route
142
- exact
143
- path={URLS.MODULES}
144
- render={() => (
145
- <Container>
146
- <Stack space="medium">
147
- <Summary
148
- keys={METRICS_WEBPACK_MODULES}
149
- data={summary}
150
- budgets={insights?.webpack?.budgets}
151
- showSummaryItemDelta={jobs.length !== 1}
152
- />
153
- <Box outline>
154
- <BundleModules
155
- jobs={jobs}
156
- setState={bundleModulesSetState}
157
- {...bundleModulesState}
158
- />
159
- </Box>
160
- </Stack>
161
- </Container>
162
- )}
163
- />
164
- <Route
165
- exact
166
- path={URLS.PACKAGES}
167
- render={({ location }) => (
168
- <Container>
169
- <Stack space="medium">
170
- <Summary
171
- keys={METRICS_WEBPACK_PACKAGES}
172
- data={summary}
173
- budgets={insights?.webpack?.budgets}
174
- showSummaryItemDelta={jobs.length !== 1}
175
- />
176
- <Box outline>
177
- <BundlePackages
178
- jobs={jobs}
179
- {...bundlePackagesState}
180
- setState={bundlePackagesSetState}
181
- key={`${location.pathname}_${location.search}`}
182
- />
183
- </Box>
184
- </Stack>
185
- </Container>
186
- )}
187
- />
188
- <Route
189
- exact
190
- path={URLS.OVERVIEW}
191
- render={() => (
192
- <Stack space="large">
193
- {duplicatePackagesInsights && (
194
- <Container>
195
- <DuplicatePackagesWarning
196
- duplicatePackagesCount={duplicatePackagesCount}
197
- showDelta={jobs.length > 1}
198
- />
199
- </Container>
200
- )}
201
- {insights?.webpack?.budgets && (
202
- <Container>
203
- <BudgetInsights source="webpack" budgets={insights.webpack.budgets} />
204
- </Container>
205
- )}
206
- <Container>
207
- <Stack space="small">
208
- <TotalSizeTypeTitle />
209
- <BundleAssetsTotalsChartBars jobs={jobs} />
210
- <Box outline>
211
- <BundleAssetsTotalsTable jobs={jobs} />
212
- </Box>
213
- </Stack>
214
- </Container>
215
- </Stack>
216
- )}
217
- />
218
- </Switch>
219
- </div>
220
- </Layout>
201
+ <div className={css.tabsContent}>
202
+ <Switch>
203
+ <Route exact path={URLS.ASSETS} component={AssetsContent} />
204
+ <Route exact path={URLS.MODULES} component={ModulesContent} />
205
+ <Route exact path={URLS.PACKAGES} component={PackagesContent} />
206
+ <Route exact path={URLS.OVERVIEW} component={OverviewContent} />
207
+ </Switch>
208
+ </div>
209
+ </Layout>
210
+ </JobsProvider>
221
211
  );
222
212
  };
223
213
 
@@ -13,12 +13,13 @@
13
13
  }
14
14
 
15
15
  .summaryContainer {
16
- padding-top: var(--space-large);
16
+ padding-top: var(--space-medium);
17
17
  padding-bottom: var(--space-small);
18
18
  }
19
19
 
20
20
  .tabsContainer {
21
21
  border-bottom: 1px solid var(--color-outline);
22
+ background: var(--color-light);
22
23
  }
23
24
 
24
25
  .tabs {
@@ -34,14 +35,14 @@
34
35
  }
35
36
 
36
37
  .tabsContent {
37
- padding-top: var(--space-large);
38
- padding-bottom: var(--space-large);
38
+ padding-top: var(--space-medium);
39
+ padding-bottom: var(--space-medium);
39
40
  min-height: 480px;
40
41
  }
41
42
 
42
43
  @media (min-width: 600px) {
43
44
  :root {
44
- --header-height: 80px;
45
+ --header-height: 72px;
45
46
  }
46
47
 
47
48
  .header {
@@ -54,4 +55,10 @@
54
55
  background-color: var(--color-background);
55
56
  border-bottom: 1px solid var(--color-outline);
56
57
  }
58
+
59
+ .tabsContainer {
60
+ position: sticky;
61
+ top: var(--header-height);
62
+ z-index: 100;
63
+ }
57
64
  }
@@ -4,21 +4,11 @@ import cx from 'classnames';
4
4
 
5
5
  import { Container } from '../../ui/container';
6
6
  import { JobsHeader } from '../../components/jobs-header';
7
- import { Logo } from '../../ui/logo';
8
-
9
7
  import css from './header.module.css';
10
8
 
11
9
  export const Header = ({ className, jobs }) => (
12
10
  <Container as="header" className={cx(css.root, className)}>
13
11
  <div className={css.inner}>
14
- <a
15
- className={css.branding}
16
- href="https://github.com/relative-ci/bundle-stats"
17
- target="_blank"
18
- rel="noopener noreferrer nofollow"
19
- >
20
- <Logo className={css.brandingLogo}>BundleStats</Logo>
21
- </a>
22
12
  <JobsHeader className={css.jobs} jobs={jobs} />
23
13
  </div>
24
14
  </Container>
@@ -1,8 +1,4 @@
1
1
  <svg width="16" height="16">
2
- <symbol fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle" viewBox="0 0 24 24" id="alert-circle" xmlns="http://www.w3.org/2000/svg">
3
- <circle cx="12" cy="12" r="10"/>
4
- <path d="M12 8v4M12 16h.01"/>
5
- </symbol>
6
2
  <symbol viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-arrow-down" id="arrow" xmlns="http://www.w3.org/2000/svg">
7
3
  <path d="M12 5v14M19 12l-7 7-7-7"/>
8
4
  </symbol>
@@ -14,10 +10,6 @@
14
10
  <circle cx="12" cy="12" r="10"/>
15
11
  <path d="M15 9l-6 6M9 9l6 6"/>
16
12
  </symbol>
17
- <symbol fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check-circle" viewBox="0 0 24 24" id="check-circle" xmlns="http://www.w3.org/2000/svg">
18
- <path d="M22 11.08V12a10 10 0 11-5.93-9.14"/>
19
- <path d="M22 4L12 14.01l-3-3"/>
20
- </symbol>
21
13
  <symbol viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-clock" id="clock" xmlns="http://www.w3.org/2000/svg">
22
14
  <circle cx="12" cy="12" r="10"/>
23
15
  <path d="M12 6v6l4 2"/>
@@ -1,4 +1,5 @@
1
1
  .fileName {
2
+ max-width: 100%;
2
3
  padding: 2px;
3
4
  background: var(--color-highlight-warning);
4
5
  }
@@ -1,16 +1,22 @@
1
- import React, { useMemo } from 'react';
1
+ import React, { useCallback, useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import cx from 'classnames';
4
4
  import { get, map } from 'lodash';
5
- import { ASSET_ENTRY_TYPE, ASSET_FILE_TYPE, ASSET_FILTERS, FILE_TYPE_LABELS } from '@bundle-stats/utils';
5
+ import {
6
+ ASSET_ENTRY_TYPE,
7
+ ASSET_FILE_TYPE,
8
+ ASSET_FILTERS,
9
+ FILE_TYPE_LABELS,
10
+ } from '@bundle-stats/utils';
6
11
 
7
12
  import config from '../../config.json';
8
13
  import I18N from '../../i18n';
9
14
  import { FlexStack } from '../../layout/flex-stack';
10
15
  import { Icon } from '../../ui/icon';
11
16
  import { FileName } from '../../ui/file-name';
12
- import { Popover } from '../../ui/popover';
17
+ import { HoverCard } from '../../ui/hover-card';
13
18
  import { Tooltip } from '../../ui/tooltip';
19
+ import { Tag } from '../../ui/tag';
14
20
  import { Filters } from '../../ui/filters';
15
21
  import { SortDropdown } from '../../ui/sort-dropdown';
16
22
  import { EmptySet } from '../../ui/empty-set';
@@ -71,48 +77,91 @@ TooltipNotPredictive.propTypes = {
71
77
  runs: PropTypes.array, // eslint-disable-line react/forbid-prop-types
72
78
  };
73
79
 
74
- const getRenderRowHeader = ({ labels, CustomComponentLink, chunks }) => (item) => {
75
- const { label, isNotPredictive, runs, isChunk, isEntry, isInitial } = item;
80
+ const RowHeader = ({ row, labels, chunks, CustomComponentLink }) => {
81
+ const { label, isNotPredictive, runs, isChunk, isEntry, isInitial } = row;
82
+ const [showHoverCard, setHoverCard] = useState(false);
83
+ const handleOnMouseEnter = useCallback(() => setHoverCard(true), [showHoverCard]);
76
84
 
77
- return (
78
- <Popover
79
- label={<FileName name={label} />}
80
- icon={
81
- <div className={css.assetInfoFlags}>
85
+ const content = useMemo(
86
+ () => (
87
+ <span className={css.assetName}>
88
+ <span className={css.assetNameTags}>
82
89
  {isNotPredictive && (
83
90
  <Tooltip className={css.notPredictive} title={<TooltipNotPredictive runs={runs} />}>
84
91
  <Icon className={css.notPredictiveIcon} glyph="warning" />
85
92
  </Tooltip>
86
93
  )}
87
94
  {isChunk && (
88
- <span title="Chunk" className={css.flagChunk}>
89
- c
90
- </span>
95
+ <Tag
96
+ className={cx(css.assetNameTag, css.assetNameTagChunk)}
97
+ title="Chunk"
98
+ size={Tag.SIZES.SMALL}
99
+ kind={Tag.KINDS.INFO}
100
+ />
91
101
  )}
92
102
  {isEntry && (
93
- <span title="Entrypoint" className={css.flagEntry}>
94
- e
95
- </span>
103
+ <Tag
104
+ className={cx(css.assetNameTag, css.assetNameTagEntry)}
105
+ title="Entrypoint"
106
+ size={Tag.SIZES.SMALL}
107
+ kind={Tag.KINDS.INFO}
108
+ />
96
109
  )}
97
110
  {isInitial && (
98
- <span title="Initial" className={css.flagInitial}>
99
- i
100
- </span>
111
+ <Tag
112
+ className={cx(css.assetNameTag, css.assetNameTagInitial)}
113
+ title="Initial"
114
+ size={Tag.SIZES.SMALL}
115
+ kind={Tag.KINDS.INFO}
116
+ />
101
117
  )}
102
- </div>
103
- }
104
- >
118
+ </span>
119
+ <FileName className={css.assetNameText} name={label} />
120
+ </span>
121
+ ),
122
+ [isChunk, isEntry, isInitial, isNotPredictive, runs],
123
+ );
124
+
125
+ if (!showHoverCard) {
126
+ return <span onMouseEnter={handleOnMouseEnter}>{content}</span>;
127
+ }
128
+
129
+ return (
130
+ <HoverCard label={content}>
105
131
  <AssetInfo
106
132
  className={css.assetInfo}
107
- item={item}
133
+ item={row}
108
134
  labels={labels}
109
135
  chunks={chunks}
110
136
  CustomComponentLink={CustomComponentLink}
111
137
  />
112
- </Popover>
138
+ </HoverCard>
113
139
  );
114
140
  };
115
141
 
142
+ RowHeader.propTypes = {
143
+ row: PropTypes.shape({
144
+ label: PropTypes.string,
145
+ isNotPredictive: PropTypes.bool,
146
+ isChunk: PropTypes.bool,
147
+ isInitial: PropTypes.bool,
148
+ isEntry: PropTypes.bool,
149
+ runs: PropTypes.arrayOf(PropTypes.object),
150
+ }).isRequired,
151
+ chunks: PropTypes.arrayOf(
152
+ PropTypes.shape({
153
+ id: PropTypes.string,
154
+ name: PropTypes.string,
155
+ }),
156
+ ),
157
+ labels: PropTypes.arrayOf(PropTypes.string).isRequired,
158
+ CustomComponentLink: PropTypes.elementType.isRequired,
159
+ };
160
+
161
+ RowHeader.defaultProps = {
162
+ chunks: [],
163
+ };
164
+
116
165
  export const BundleAssets = (props) => {
117
166
  const {
118
167
  className,
@@ -141,11 +190,16 @@ export const BundleAssets = (props) => {
141
190
  />
142
191
  );
143
192
 
144
- const chunks = jobs[0]?.meta?.webpack?.chunks || [];
145
-
146
- const renderRowHeader = useMemo(
147
- () => getRenderRowHeader({ labels: map(jobs, 'label'), CustomComponentLink, chunks }),
148
- [jobs, chunks],
193
+ const renderRowHeader = useCallback(
194
+ (row) => (
195
+ <RowHeader
196
+ row={row}
197
+ labels={map(jobs, 'label')}
198
+ chunks={jobs[0]?.meta?.webpack?.chunks || []}
199
+ CustomComponentLink={CustomComponentLink}
200
+ />
201
+ ),
202
+ [jobs, CustomComponentLink],
149
203
  );
150
204
 
151
205
  return (
@@ -153,7 +207,7 @@ export const BundleAssets = (props) => {
153
207
  <Toolbar
154
208
  className={css.toolbar}
155
209
  renderActions={({ actionClassName }) => (
156
- <FlexStack space="xsmall" className={cx(css.dropdown, actionClassName)}>
210
+ <FlexStack space="xxsmall" className={cx(css.dropdown, actionClassName)}>
157
211
  <SortDropdown fields={sortFields} {...sort} onChange={updateSort} />
158
212
  <MetricsTableOptions
159
213
  handleViewAll={resetAllFilters}
@@ -162,7 +216,7 @@ export const BundleAssets = (props) => {
162
216
  </FlexStack>
163
217
  )}
164
218
  >
165
- <FlexStack>
219
+ <FlexStack space="xxsmall">
166
220
  <MetricsTableSearch
167
221
  className={css.toolbarSearch}
168
222
  placeholder="Search by name"
@@ -8,6 +8,8 @@
8
8
  margin-right: -1px; /** collapse border */
9
9
  }
10
10
 
11
+ .assetName {}
12
+
11
13
  .notPredictive {
12
14
  margin-right: var(--space-xxsmall);
13
15
  display: inline-block;
@@ -21,50 +23,46 @@
21
23
  vertical-align: top;
22
24
  }
23
25
 
24
- .assetInfoFlags {
25
- display: inline-block;
26
+ .assetNameTags {
27
+ display: inline;
26
28
  margin-right: var(--space-xxxsmall);
27
29
  }
28
30
 
29
- .assetInfoFlags:empty {
31
+ .assetNameTags:empty {
30
32
  display: none;
31
33
  }
32
34
 
33
- .flag {
34
- display: inline-block;
35
- width: var(--space-xsmall);
36
- height: var(--space-xsmall);
37
- font-family: var(--font-family);
38
- font-size: 8px;
39
- font-weight: bold;
40
- background: var(--color-highlight);
41
- color: var(--color-text-light);
42
- line-height: var(--space-xsmall);
43
- text-align: center;
44
- text-transform: uppercase;
35
+ .assetNameTag {
45
36
  vertical-align: middle;
46
37
  }
47
38
 
48
- .flag + .flag {
39
+ .assetNameTag + .assetNameTag {
49
40
  margin-left: 2px;
50
41
  }
51
42
 
52
- .flagEntry {
53
- composes: flag;
43
+ .assetNameTagEntry {
54
44
  background: var(--color-info-light);
55
- color: var(--color-background);
56
45
  }
57
46
 
58
- .flagInitial {
59
- composes: flag;
47
+ .assetNameTagEntry::before {
48
+ content: 'e';
49
+ }
50
+
51
+ .assetNameTagInitial {
60
52
  background: var(--color-info-light);
61
- color: var(--color-background);
62
53
  }
63
54
 
64
- .flagChunk {
65
- composes: flag;
66
- background: var(--color-info);
67
- color: var(--color-background);
55
+ .assetNameTagInitial::before {
56
+ content: 'i';
57
+ }
58
+
59
+ .assetNameTagChunk::before {
60
+ content: 'c';
61
+ }
62
+
63
+ .assetNameText {
64
+ display: inline;
65
+ vertical-align: middle;
68
66
  }
69
67
 
70
68
  /* Tooltip not predictive */