Skip to content

Commit 25ccdb3

Browse files
AregSoftAreg HakobyanGaroGabrielyan
authored
fix(ProgressBar): change error prop as status (#360)
* fix(ProgressBar): remove error prop and add status prop to improve component status handling * fix(ProgressBar): use Text component for texts * fix(ProgressBar): progress bar rendering with conditions and tests * fix(ProgressBar): remove redundant conditions for status bar * fix(ProgressBar): types * fix(ProgressBar): simplify logic of the component * fix(ProgressBar): percent text variant --------- Co-authored-by: Areg Hakobyan <[email protected]> Co-authored-by: Galust <[email protected]>
1 parent b3c9a25 commit 25ccdb3

File tree

4 files changed

+62
-66
lines changed

4 files changed

+62
-66
lines changed

src/components/molecules/ProgressBar/ProgressBar.scss

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,6 @@
3737
}
3838

3939
&_size {
40-
&_large,
41-
&_medium {
42-
#{ $this }__status {
43-
font-family: var(--guit-sem-font-label-medium-default-semibold-font-family);
44-
font-size: var(--guit-sem-font-label-medium-default-semibold-font-size);
45-
font-weight: var(--guit-sem-font-label-medium-default-medium-font-weight);
46-
line-height: var(--guit-sem-font-label-medium-default-semibold-line-height);
47-
}
48-
}
49-
5040
&_large {
5141
#{ $this }__track {
5242
height: var(--guit-sem-dimension-height-xsmall);
@@ -66,18 +56,11 @@
6656
height: var(--guit-sem-dimension-height-3xsmall);
6757
border-radius: var(--guit-ref-radius-3xsmall);
6858
}
69-
70-
#{ $this }__status {
71-
font-family: var(--guit-sem-font-label-small-default-medium-font-family);
72-
font-size: var(--guit-sem-font-label-small-default-medium-font-size);
73-
font-weight: var(--guit-sem-font-label-small-default-medium-font-weight);
74-
line-height: var(--guit-sem-font-label-small-default-medium-line-height);
75-
}
7659
}
7760
}
7861

79-
&_color {
80-
&_default {
62+
&_status {
63+
&_rest {
8164
#{ $this }__fill,
8265
#{ $this }__loadingBar {
8366
background-color: var(--guit-sem-color-background-brand-2);
@@ -127,7 +110,7 @@
127110
word-break: break-word;
128111
}
129112

130-
&__status {
113+
&__statusBar {
131114
margin-inline-start: auto;
132115
color: var(--guit-sem-color-foreground-neutral-2);
133116
flex: 0 0 auto;

src/components/molecules/ProgressBar/ProgressBar.stories.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,16 @@ const meta: Meta<IProgressBarProps> = {
1717
percent: args({ control: "number", ...propCategory.content }),
1818
infoText: args({ control: "text", ...propCategory.content }),
1919
label: args({ control: "text", ...propCategory.content }),
20-
error: args({ control: "boolean", ...propCategory.states })
20+
status: args({ control: "select", ...propCategory.states })
2121
},
2222
args: {
2323
uploadingText: "Uploading",
2424
type: "determinate",
2525
helperText: "Helper Text",
2626
percent: 44,
2727
size: "medium",
28-
label: "Label"
28+
label: "Label",
29+
status: "rest"
2930
}
3031
};
3132

src/components/molecules/ProgressBar/ProgressBar.test.tsx

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { mount, ReactWrapper } from "enzyme";
44
// Components
55
import HelperText from "@components/atoms/HelperText";
66
import Label from "@components/atoms/Label";
7+
import Text from "@components/atoms/Text";
78

89
import ProgressBar, { IProgressBarProps } from "./index";
910

@@ -47,21 +48,26 @@ describe("ProgressBar ", () => {
4748
const uploadingText = "uploadingText";
4849
const percent = 33;
4950
const wrapper = setup.setProps({ uploadingText, percent });
50-
51-
expect(wrapper.find(".progressBar__uploadingText").text()).toStrictEqual(`${uploadingText}`);
51+
expect(
52+
wrapper
53+
.find(Text)
54+
.findWhere((item) => item.hasClass("progressBar__uploadingText"))
55+
.at(1)
56+
.text()
57+
).toStrictEqual(`${uploadingText}`);
5258
});
5359

5460
it("renders percent prop correctly", () => {
5561
const percent = 33;
5662
const wrapper = setup.setProps({ percent });
57-
58-
expect(wrapper.find(".progressBar__percent").text()).toStrictEqual(`${percent}%`);
63+
expect(wrapper.find(Text).text()).toStrictEqual(`${percent}%`);
5964
});
6065

61-
it("renders error prop correctly", () => {
62-
const wrapper = setup.setProps({ error: true });
66+
it.each<IProgressBarProps["status"]>(["rest", "warning", "error"])("should have %s status", (status) => {
67+
const wrapper = setup.setProps({ status });
68+
const className = status === "warning" ? "rest" : status;
6369
wrapper.update();
64-
expect(wrapper.find(".progressBar").hasClass(`progressBar_color_error`)).toBeTruthy();
70+
expect(wrapper.find(".progressBar").hasClass(`progressBar_status_${className}`)).toBeTruthy();
6571
});
6672

6773
it.each<IProgressBarProps["size"]>(["large", "medium", "small"])("should have %s size", (size) => {

src/components/molecules/ProgressBar/ProgressBar.tsx

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import React, { FC, useEffect, useMemo, useState } from "react";
1+
import React, { FC, useMemo } from "react";
22
import classNames from "classnames";
33

44
// Components
55
import HelperText from "@components/atoms/HelperText";
66
import Label from "@components/atoms/Label";
7+
import Text from "@components/atoms/Text";
78

89
// Styles
910
import "./ProgressBar.scss";
@@ -31,10 +32,10 @@ interface IProgressBarProps {
3132
*/
3233
type?: "determinate" | "indeterminate";
3334
/**
34-
* Indicates an error state for the progress bar.<br>
35-
* When `true`, the progress bar appears in the error style.
35+
* Determines the `ProgressBar` appearance based on its status.<br>
36+
* Possible values: `rest | warning | error`
3637
*/
37-
error?: boolean;
38+
status?: "rest" | "warning" | "error";
3839
/**
3940
* Adds supplementary information below the progress bar.
4041
*/
@@ -54,84 +55,89 @@ interface IProgressBarProps {
5455
className?: string;
5556
}
5657

57-
const helperTextTypeMap = {
58-
default: "rest",
59-
success: "rest",
60-
error: "error"
61-
} as const;
62-
6358
const helperTextAndLabelSizeMap = {
6459
large: "medium",
6560
medium: "medium",
6661
small: "small"
6762
} as const;
6863

64+
const textVariantMap = {
65+
large: "labelMediumMedium",
66+
medium: "labelMediumMedium",
67+
small: "labelSmallMedium"
68+
} as const;
69+
6970
/**
7071
* A progress bar offers visual feedback on the status and duration of a process, such as a download, file transfer, or installation, helping users understand how much longer they need to wait.
7172
*/
7273
const ProgressBar: FC<IProgressBarProps> = ({
7374
className,
7475
size = "medium",
7576
type = "determinate",
76-
error,
77+
status = "rest",
7778
helperText,
7879
percent,
7980
uploadingText,
8081
infoText,
8182
label
8283
}) => {
83-
const [status, setStatus] = useState<"default" | "success" | "error">("default");
84-
8584
const isDeterminate = type === "determinate";
86-
const isTypeDefault = status === "default";
85+
const isTypeRest = status === "rest";
8786
const isPercentLowerThanMax = percent !== undefined && percent < 100;
87+
const isError = status === "error";
88+
const isSuccess = percent === 100;
89+
const effectiveType = isError ? "determinate" : type;
90+
const isRestOrWarning = status === "rest" || status === "warning";
8891

8992
const processedPercent = useMemo(() => {
9093
let result = percent || 0;
9194

92-
if (result < 0 && !error) result = 0;
93-
if (result >= 100 || error) result = 100;
95+
if (result < 0 && !isError) result = 0;
96+
if (result >= 100 || isError) result = 100;
9497

9598
return `${result}%`;
96-
}, [percent, error]);
97-
98-
useEffect(() => {
99-
if (error && status !== "error") {
100-
setStatus("error");
101-
} else if (percent !== undefined && !error) {
102-
if (percent >= 100 && status !== "success" && isDeterminate) {
103-
setStatus("success");
104-
} else if ((!isTypeDefault && isPercentLowerThanMax && isDeterminate) || !isDeterminate) {
105-
setStatus("default");
106-
}
107-
}
108-
}, [error, isTypeDefault, status, percent, isDeterminate]);
99+
}, [percent, isError]);
109100

110101
return (
111102
<div
112103
className={classNames(
113-
`progressBar progressBar_type_${error ? "determinate" : type} progressBar_size_${size} progressBar_color_${status}`,
114-
className
104+
"progressBar",
105+
`progressBar_type_${effectiveType}`,
106+
`progressBar_size_${size}`,
107+
className,
108+
{
109+
progressBar_status_error: isError,
110+
progressBar_status_success: isSuccess,
111+
progressBar_status_rest: isRestOrWarning
112+
}
115113
)}
116114
>
117115
<Label text={label} size={helperTextAndLabelSizeMap[size]} infoText={infoText} />
118116
<div className="progressBar__track">
119-
{(isDeterminate || error) && <div className="progressBar__fill" style={{ width: processedPercent }} />}
117+
{(isDeterminate || isError) && (
118+
<div className="progressBar__fill" style={{ width: processedPercent }} />
119+
)}
120120
<div className="progressBar__loadingBar" />
121121
</div>
122122
<div className="progressBar__info">
123123
{helperText && (
124124
<HelperText
125125
text={helperText}
126126
size={helperTextAndLabelSizeMap[size]}
127-
status={helperTextTypeMap[status]}
127+
status={status}
128128
className="progressBar__helperText"
129129
/>
130130
)}
131-
{isDeterminate && isTypeDefault && isPercentLowerThanMax && (
132-
<p className="progressBar__status">
133-
<span className="progressBar__uploadingText">{uploadingText}</span>
134-
<span className="progressBar__percent">{processedPercent}</span>
131+
{isDeterminate && isTypeRest && isPercentLowerThanMax && (
132+
<p className="progressBar__statusBar">
133+
{uploadingText && (
134+
<Text as="span" variant={textVariantMap[size]} className="progressBar__uploadingText">
135+
{uploadingText}
136+
</Text>
137+
)}
138+
<Text as="span" variant={textVariantMap[size]} className="progressBar__percent">
139+
{processedPercent}
140+
</Text>
135141
</p>
136142
)}
137143
</div>

0 commit comments

Comments
 (0)