Skip to content

Commit 559ac45

Browse files
committed
feat: ProgressIndicator clone
#60
1 parent a51853f commit 559ac45

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { HTMLAttributes, PropsWithChildren, forwardRef } from 'react';
2+
3+
import { progressIndicatorCss, stepCss } from './styles';
4+
5+
export interface ProgressIndicatorProps extends Omit<HTMLAttributes<HTMLDivElement>, 'style'> {
6+
mode?: 'horizontal' | 'vertical';
7+
totalStep: number;
8+
currentStep: number;
9+
}
10+
11+
export const ProgressIndicator = forwardRef<HTMLDivElement, PropsWithChildren<ProgressIndicatorProps>>(
12+
({ mode = 'horizontal', totalStep, currentStep, children, ...rest }, ref) => {
13+
const flexDirection = mode === 'horizontal' ? 'row' : 'column';
14+
const currentStepIndex = Math.min(totalStep, currentStep) - 1;
15+
const basis = 100 / totalStep;
16+
17+
return (
18+
<div ref={ref} {...rest} css={progressIndicatorCss({ flexDirection })}>
19+
{Array.from({ length: totalStep }).map((_, index) => (
20+
<ProgressIndicator.Step key={index} isCurrent={index === currentStepIndex} basis={basis} />
21+
))}
22+
{children}
23+
</div>
24+
);
25+
},
26+
) as React.ForwardRefExoticComponent<ProgressIndicatorProps> & { Step: typeof Step };
27+
28+
export interface StepProps extends HTMLAttributes<HTMLSpanElement> {
29+
basis: number;
30+
isCurrent: boolean;
31+
}
32+
33+
const Step = ({ isCurrent, basis, ...rest }: StepProps) => {
34+
let color = '#E1E1E1';
35+
36+
if (isCurrent) {
37+
color = '#FF7664';
38+
}
39+
40+
return <span {...rest} css={stepCss({ basis, color })} />;
41+
};
42+
43+
ProgressIndicator.displayName = 'ProgressIndicator';
44+
ProgressIndicator.Step = Step;
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { css } from '@emotion/react';
2+
3+
import { ProgressIndicatorCssArgs, StepCssArgs } from './type';
4+
5+
export const progressIndicatorCss = ({ flexDirection }: ProgressIndicatorCssArgs) =>
6+
css({ width: '100%', display: 'flex', flexWrap: 'nowrap', flexDirection });
7+
8+
export const stepCss = ({ basis, color }: StepCssArgs) =>
9+
css({
10+
boxSizing: 'border-box',
11+
flex: `${basis}% 1 1`,
12+
height: '4px',
13+
backgroundColor: color,
14+
borderRadius: '8px',
15+
margin: '2px',
16+
});
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export type ProgressIndicatorCssArgs = {
2+
flexDirection: 'row' | 'column';
3+
};
4+
5+
export type StepCssArgs = {
6+
color: string;
7+
basis: number;
8+
};

0 commit comments

Comments
 (0)