Skip to content

Commit

Permalink
feat(ui): SummaryItem - budgets
Browse files Browse the repository at this point in the history
  • Loading branch information
vio committed Nov 28, 2021
1 parent 857cbd8 commit dfa9c1e
Show file tree
Hide file tree
Showing 4 changed files with 188 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Storyshots Components/SummaryItem Budget Over 1`] = `
<div>
<Component />
<IconSprite
height="16"
style={
Object {
"height": 0,
"position": "absolute",
"width": 0,
}
}
width="16"
/>
</div>
`;

exports[`Storyshots Components/SummaryItem Budget Under 1`] = `
<div>
<Component />
<IconSprite
height="16"
style={
Object {
"height": 0,
"position": "absolute",
"width": 0,
}
}
width="16"
/>
</div>
`;

exports[`Storyshots Components/SummaryItem Loading 1`] = `
<div>
<Component />
Expand Down
59 changes: 58 additions & 1 deletion packages/ui/src/components/summary-item/summary-item.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import PropTypes from 'prop-types';
import cx from 'classnames';
import { getGlobalMetricType, getMetricRunInfo } from '@bundle-stats/utils';

import { Icon } from '../../ui/icon';
import { Popover } from '../../ui/popover';
import { Tooltip } from '../../ui/tooltip';
import { Skeleton } from '../../ui/skeleton';
import { Stack } from '../../layout/stack';
import { FlexStack } from '../../layout/flex-stack';
Expand Down Expand Up @@ -40,6 +42,48 @@ MetricInfo.defaultProps = {
url: '',
};

const BudgetInfo = ({ className = '', budget, metric }) => {
const rootClassName = cx(
css.budgetIcon,
budget.overBudget ? css.budgetIconWarning : css.budgetIconSuccess,
className,
);

return (
<Tooltip
className={rootClassName}
title={
<>
{`Value is ${budget.overBudget ? 'over' : 'under'} `}
{metric.formatter(budget.budget)}
{` budget`}
</>
}
>
<Icon
glyph={budget.overBudget ? Icon.ICONS.WARNING : Icon.ICONS.CHECK_CIRCLE}
size="medium"
/>
</Tooltip>
);
};

BudgetInfo.propTypes = {
budget: PropTypes.shape({
value: PropTypes.number,
budget: PropTypes.number,
overBudget: PropTypes.bool,
}).isRequired,
metric: PropTypes.shape({
formatter: PropTypes.func,
}).isRequired,
className: PropTypes.string,
};

BudgetInfo.defaultProps = {
className: '',
};

export const SummaryItem = ({
className,
as: Component,
Expand All @@ -49,6 +93,7 @@ export const SummaryItem = ({
loading,
showDelta,
showMetricDescription,
budget,
...props
}) => {
const { baseline, current } = data || { baseline: 0, current: 0 };
Expand All @@ -64,18 +109,22 @@ export const SummaryItem = ({
showMetricDescription && css.showMetricDescription,
showMetricDescriptionTooltip && css.showMetricDescription,
showDelta && css.showDelta,
budget?.overBudget && css.budgetOver,
budget?.overBudget === false && css.budgetUnder,
);

return (
<Stack space="xxsmall" as={Component} className={rootClassName} {...props}>
<FlexStack as="h3" space="xxxsmall" className={css.title}>
<span>{metric.label}</span>
<span className={css.titleLabel}>{metric.label}</span>

{showMetricDescriptionTooltip && (
<Popover className={css.icon} icon="help">
<MetricInfo {...metric} />
</Popover>
)}

{budget && <BudgetInfo metric={metric} budget={budget} />}
</FlexStack>

<Stack>
Expand Down Expand Up @@ -117,6 +166,7 @@ SummaryItem.defaultProps = {
loading: false,
showMetricDescription: false,
showDelta: true,
budget: undefined,
};

SummaryItem.propTypes = {
Expand All @@ -143,4 +193,11 @@ SummaryItem.propTypes = {

/** Show delta */
showDelta: PropTypes.bool,

/** Budget data */
budget: PropTypes.shape({
value: PropTypes.number,
budget: PropTypes.number,
overBudget: PropTypes.bool,
}),
};
33 changes: 33 additions & 0 deletions packages/ui/src/components/summary-item/summary-item.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@
white-space: nowrap;
}

.titleLabel {
flex: 0 0 auto;
}

.readMoreBtn {
appearance: none;
padding: 0;
Expand All @@ -27,6 +31,11 @@
text-decoration: none;
}

.budgetIcon {
flex: 0 0 auto;
margin-left: auto !important;
}

.currentMetric {
display: block;
color: var(--color-heading);
Expand Down Expand Up @@ -56,6 +65,30 @@
width: 5em;
}

/* Budget over */
.budgetOver .budgetIcon {
color: var(--color-danger-light);
}

.budgetOver .budgetIcon:hover,
.budgetOver .budgetIcon:focus,
.budgetOver .budgetIcon:active
{
color: var(--color-danger);
}

/* Budget under */
.budgetUnder .budgetIcon {
color: var(--color-success-light);
}

.budgetUnder .budgetIcon:hover,
.budgetUnder .budgetIcon:focus,
.budgetUnder .budgetIcon:active
{
color: var(--color-success);
}

/* Size large */
.large .currentMetric {
font-size: var(--size-xxxlarge);
Expand Down
110 changes: 63 additions & 47 deletions packages/ui/src/components/summary-item/summary-item.stories.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,53 +5,69 @@ import { SummaryItem } from './summary-item';
export default {
title: 'Components/SummaryItem',
component: SummaryItem,
};

export const Standard = () => (
<SummaryItem
loading={false}
id="webpack.totalSizeByTypeALL"
data={{
current: 120 * 1000,
baseline: 100 * 1000,
}}
/>
);

export const SizeLarge = () => (
<SummaryItem
size="large"
loading={false}
id="webpack.totalSizeByTypeALL"
data={{
decorators: [
(Story) => (
<div style={{ maxWidth: '320px' }}>
<Story />
</div>
),
],
args: {
loading: false,
id: 'webpack.totalSizeByTypeALL',
data: {
current: 120 * 1000,
baseline: 100 * 1000,
}}
/>
);

export const ShowMetricDescription = () => (
<SummaryItem
loading={false}
id="webpack.totalSizeByTypeALL"
data={{
current: 120 * 1000,
baseline: 100 * 1000,
}}
showMetricDescription
/>
);

export const ShowDeltaFalse = () => (
<SummaryItem
loading={false}
id="webpack.totalSizeByTypeALL"
data={{
current: 120 * 1000,
baseline: 0,
}}
showDelta={false}
/>
);
},
},
};

const Template = (args) => <SummaryItem {...args} />;

export const Standard = Template.bind();

export const SizeLarge = Template.bind();

SizeLarge.args = {
size: 'large',
};

export const ShowMetricDescription = Template.bind();

export const Loading = () => <SummaryItem loading id="webpack.totalSizeByTypeALL" />;
ShowMetricDescription.args = {
showMetricDescription: true,
};

export const ShowDeltaFalse = Template.bind();

ShowDeltaFalse.args = {
showDelta: false,
};

export const BudgetOver = Template.bind();

BudgetOver.args = {
showMetricDescription: true,
budget: {
value: 120 * 1000,
budget: 100 * 1000,
overBudget: true,
},
};

export const BudgetUnder = Template.bind();

BudgetUnder.args = {
showMetricDescription: true,
budget: {
value: 120 * 1000,
budget: 120 * 1024,
overBudget: false,
},
};

export const Loading = Template.bind();

Loading.args = {
loading: true,
};

0 comments on commit dfa9c1e

Please sign in to comment.