Skip to content

Commit

Permalink
Merge pull request #61 from Kernel360/common-component-progress-bar
Browse files Browse the repository at this point in the history
공통 컴포넌트: ProgressBar
  • Loading branch information
seoye0ng authored Jan 10, 2024
2 parents 20d52e3 + 0f37a4f commit 9cf3e52
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 3 deletions.
43 changes: 43 additions & 0 deletions src/components/shared/progress-bar/ProgressBar.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
.container {
position: relative;
width: 185px;
height: 24px;
margin: 0 auto;

.progressBar {
position: absolute;
top: 50%;
width: inherit;
height: 3px;
transform: translateY(-50%);
background-color: var(--gray);
}

.progress {
position: absolute;
top: 50%;
height: 3px;
transform: translateY(-50%);
transition: all 0.25s ease-in-out;
background-color: var(--primary);
}

.progressSteps {
display: flex;
position: absolute;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
transform: translateX(-50%);
transition: all 0.3s ease-in-out;
border-radius: 50%;
background-color: var(--gray);
color: var(--white);
font-size: 12px;

&.active {
background-color: var(--primary);
}
}
}
60 changes: 60 additions & 0 deletions src/components/shared/progress-bar/ProgressBar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import type { Meta, StoryObj } from '@storybook/react';

import ProgressBar from './ProgressBar';

const meta: Meta = {
title: 'Shared/ProgressBar',
component: ProgressBar,
tags: ['autodocs'],
argTypes: {
progressCount: {
type: 'number',
min: 1,
max: 5,
step: 1,
},
currentStep: {
control: {
type: 'range',
min: 1,
max: 5,
step: 1,
},
},
},
}satisfies Meta<typeof ProgressBar>;

export default meta;
type Story = StoryObj<typeof meta>;

export const CarDetailInput: Story = {
args: {
progressCount: 5,
currentStep: 3,
},
};

export const CarWashDetailInput: Story = {
args: {
progressCount: 3,
currentStep: 1,
},
};

// CarWashDetailInput에 대한 argTypes를 따로 설정
CarWashDetailInput.argTypes = {
progressCount: {
type: 'number',
min: 1,
max: 5,
step: 1,
},
currentStep: {
control: {
type: 'range',
min: 1,
max: 3, // 원하는 max 값으로 설정
step: 1,
},
},
};
53 changes: 53 additions & 0 deletions src/components/shared/progress-bar/ProgressBar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';

import { useMemo } from 'react';

import classNames from 'classnames/bind';

import styles from './ProgressBar.module.scss';

const cx = classNames.bind(styles);

interface ProgressBarProps {
progressCount?:number;
currentStep?:number;
setCurrentStep: (num: number) => void;
}

function ProgressBar({ progressCount = 5, currentStep = 1, setCurrentStep }:ProgressBarProps) {
// progressCountArr는 currentStep가 변경되지 않는 한 재생성 X
const progressCountArr = useMemo(() => {
return Array.from({ length: progressCount }, (_, i) => { return i + 1; });
}, [progressCount]);

// progressBarWidth는 currentStep가 변경될 때만 재생성
const progressBarWidth = useMemo(() => { return `${((currentStep - 1) / (progressCount - 1)) * 100}%`; }, [currentStep, progressCount]);

const handleClick = (num: number) => {
setCurrentStep(num);
};

return (
<div className={cx('container')}>
<div className={cx('progressBar')} />
<div className={cx('progress')} style={{ width: progressBarWidth }} />
<div>
{progressCountArr.map((num, idx) => {
const leftPosition = `${(idx / (progressCount - 1)) * 100}%`;
return (
<button
key={num}
className={cx('progressSteps', { active: currentStep >= num })}
style={{ left: leftPosition }}
onClick={() => { return handleClick(num); }}
>
{num}
</button>
);
})}
</div>
</div>
);
}

export default ProgressBar;
6 changes: 3 additions & 3 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@
],
"@stories/*": [
"src/stories/*"
],
},
]
}
},
"include": [
"next-env.d.ts",
Expand All @@ -80,4 +80,4 @@
"exclude": [
"node_modules"
]
}
}

0 comments on commit 9cf3e52

Please sign in to comment.