Skip to content

Commit

Permalink
SizeChart
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Perez committed Oct 22, 2024
1 parent d056b5a commit d12b8de
Show file tree
Hide file tree
Showing 3 changed files with 275 additions and 0 deletions.
79 changes: 79 additions & 0 deletions src/components/SizeChart/SizeChart.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// This file is part of MinIO Design System
// Copyright (c) 2023 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import React, { Fragment } from "react";
import { Meta, Story } from "@storybook/react";

import StoryThemeProvider from "../../../../../Downloads/mds-master 2/src/utils/StoryThemeProvider";
import TestIcon from "../../../../../Downloads/mds-master 2/src/utils/TestIcon";
import { Button, GlobalStyles } from "../../../../../Downloads/mds-master 2/src/components";
import SizeChart from "./SizeChart";
import { SizeChartProps } from "./SizeChart.types";

export default {
title: "MDS/Data/SizeChart",
component: SizeChart,
argTypes: {},
} as Meta<typeof SizeChart>;

const Template: Story<SizeChartProps> = (args) => (
<StoryThemeProvider>
<GlobalStyles />
<SizeChart {...args} />
</StoryThemeProvider>
);

export const Default = Template.bind({});
Default.args = {
usedBytes: 45000,
totalBytes: 100000,
};

export const WarningSpace = Template.bind({});
WarningSpace.args = {
usedBytes: 85000,
totalBytes: 100000,
};

export const DangerSpace = Template.bind({});
DangerSpace.args = {
usedBytes: 95000,
totalBytes: 100000,
};

export const WithLabel = Template.bind({});
WithLabel.args = {
usedBytes: 95000,
totalBytes: 100000,
label: true,
};

export const WithChartLabel = Template.bind({});
WithChartLabel.args = {
usedBytes: 9504400,
totalBytes: 103840000,
label: true,
chartLabel: "Reported Usage",
};

export const CustomSize = Template.bind({});
CustomSize.args = {
usedBytes: 95000,
totalBytes: 100000,
label: true,
width: 50,
height: 50,
};
164 changes: 164 additions & 0 deletions src/components/SizeChart/SizeChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
// This file is part of MinIO Design System
// Copyright (c) 2023 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import React, { FC, SVGProps, useEffect, useRef } from "react";
import get from "lodash/get";
import styled from "styled-components";

import { lightColors } from "../../../../../Downloads/mds-master 2/src/global/themes";
import { calculateBytes, overridePropsParse } from "../../../../../Downloads/mds-master 2/src/global/utils";
import { SizeChartConstructProps, SizeChartProps } from "./SizeChart.types";

const SizeChartBase = styled.svg<SVGProps<any> & SizeChartConstructProps>(
({ theme, usedBytes, totalBytes, chartLabel, sx }) => {
const percUsed = (usedBytes * 100) / totalBytes;

let color = get(theme, "signalColors.main", lightColors.mainBlue);

if (percUsed >= 90) {
color = get(theme, "signalColors.danger", lightColors.mainRed);
} else if (percUsed >= 80) {
color = get(theme, "signalColors.warning", lightColors.mainOrange);
}

return {
"& .usedSpace": {
stroke: color,
},
"& .availableSpace": {
stroke: get(theme, "signalColors.disabled", lightColors.disabledGrey),
},
"& .chartText": {
fill: "#000",
transform: "translateY(0.25em)",
},
"& .chartNumber": {
fontSize: "0.3em",
lineHeight: 1,
textAnchor: "middle",
transform:
chartLabel !== "" ? "translateY(-0.50em)" : "translateY(-0.25em)",
fontWeight: "bold",
fill: get(theme, "fontColor", lightColors.defaultFontColor),
},
"& .chartLabel": {
fontSize: "0.2em",
textAnchor: "middle",
transform: "translateY(0.7em)",
whiteSpace: "normal",
fontWeight: "bold",
fill: get(theme, "mutedText", lightColors.mutedText),
},
...overridePropsParse(sx, theme),
};
},
);

const SizeChart: FC<SizeChartProps> = ({
width = "150",
height = "150",
usedBytes,
totalBytes,
label,
chartLabel = "",
sx,
}) => {
const val1D = useRef<SVGCircleElement>(null);
const val2D = useRef<SVGCircleElement>(null);

useEffect(() => {
setTimeout(function () {
if (val1D?.current) {
val1D.current.style.transition =
"stroke-dasharray 0.5s ease-in-out, stroke-dashoffset 0.5s ease-in-out";
val1D.current.style.strokeDasharray = "100 0";
}
}, 20);
}, []);

useEffect(() => {
const val1 = usedBytes;
const val2 = totalBytes - usedBytes;

const total = val1 + val2;

const per1 = (val1 / total) * 100;
const per2 = (val2 / total) * 100;
const offset = 25;

if (val1D?.current && val2D?.current) {
val1D.current.style.transition =
"stroke-dasharray 0.5s ease-in-out, stroke-dashoffset 0.5s ease-in-out";
val1D.current.style.strokeDasharray = per1 + " " + (100 - per1);
val1D.current.style.strokeDashoffset = `${offset}`;

val2D.current.style.transition =
"stroke-dasharray 0.5s ease-in-out, stroke-dashoffset 0.5s ease-in-out";
val2D.current.style.strokeDasharray = per2 + " " + (100 - per2);
val2D.current.style.strokeDashoffset = `${100 - per1 + offset}`;
}
}, [usedBytes, totalBytes]);

const usedSizeUnits = calculateBytes(usedBytes);

return (
<SizeChartBase
width={width}
height={height}
viewBox="0 0 42 42"
usedBytes={usedBytes}
totalBytes={totalBytes}
sx={sx}
chartLabel={chartLabel}
>
<circle
className={"usedSpace"}
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
strokeWidth="3"
strokeDasharray="100 0"
strokeDashoffset="25"
ref={val1D}
/>
<circle
className={"availableSpace"}
cx="21"
cy="21"
r="15.91549430918954"
fill="transparent"
stroke="#ff0000"
strokeWidth="3"
strokeDasharray="100 0"
strokeDashoffset="25"
ref={val2D}
/>
{label && (
<g className="chartText">
<text x="50%" y="50%" className="chartNumber">
{usedSizeUnits.total}&nbsp;{usedSizeUnits.unit}
</text>
<text x="50%" y="50%" className="chartLabel">
{chartLabel}
</text>
</g>
)}
</SizeChartBase>
);
};

export default SizeChart;
32 changes: 32 additions & 0 deletions src/components/SizeChart/SizeChart.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// This file is part of MinIO Design System
// Copyright (c) 2023 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import { OverrideTheme } from "../../../../../Downloads/mds-master 2/src/global/global.types";

export interface SizeChartMain {
label: boolean;
width?: string;
height?: string;
}

export interface SizeChartConstructProps {
usedBytes: number;
totalBytes: number;
chartLabel?: string;
sx?: OverrideTheme;
}

export type SizeChartProps = SizeChartMain & SizeChartConstructProps;

0 comments on commit d12b8de

Please sign in to comment.