-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add ProgressBar component with customizable properties and styles
- Loading branch information
1 parent
e5c886c
commit c14e50e
Showing
4 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// import variables.scss | ||
@import '../../scss/variables.scss'; | ||
|
||
// Progress bar variables | ||
$progress-height-sm: 20px; // Increased to accommodate text | ||
$progress-height-md: 24px; // Increased to accommodate text | ||
$progress-height-lg: 32px; // Increased to accommodate text | ||
$progress-border-radius: .5rem; | ||
$progress-background: $gray-900; | ||
$progress-fill-color: $pink; | ||
$transition-duration: 0.3s; | ||
|
||
.aml__progress-bar { | ||
width: 100%; | ||
position: relative; | ||
|
||
&-container { | ||
background-color: $progress-background; | ||
border-radius: $progress-border-radius; | ||
border: 1px solid $gray-200; | ||
overflow: hidden; | ||
width: 100%; | ||
height: $progress-height-md; | ||
position: relative; | ||
} | ||
|
||
&-fill { | ||
background-color: $progress-fill-color; | ||
height: 100%; | ||
border-radius: $progress-border-radius; | ||
transition: width $transition-duration ease-in-out; | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
} | ||
|
||
&-content { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
width: 100%; | ||
height: 100%; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
gap: 1rem; | ||
padding: 0 10px; | ||
z-index: 1; | ||
pointer-events: none; | ||
color: #fff; | ||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); | ||
font-size: 14px; | ||
|
||
&.size-sm { | ||
font-size: 12px; | ||
} | ||
|
||
&.size-md { | ||
font-size: 14px; | ||
} | ||
|
||
&.size-lg { | ||
font-size: 16px; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import { render } from '@testing-library/react'; | ||
import ProgressBar from './ProgressBar'; | ||
import { describe, it, expect } from 'vitest'; | ||
|
||
describe('ProgressBar', () => { | ||
it('renders correctly with default props', () => { | ||
const { container } = render(<ProgressBar value={50} />); | ||
|
||
const progressBar = container.querySelector('.aml__progress-bar'); | ||
const progressFill = container.querySelector('.aml__progress-bar-fill'); | ||
const content = container.querySelector('.aml__progress-bar-content'); | ||
|
||
expect(progressBar).toBeTruthy(); | ||
expect(progressFill).toBeTruthy(); | ||
expect(content).toBeTruthy(); | ||
expect(progressFill?.getAttribute('style')).toBe('width: 50%;'); | ||
}); | ||
|
||
it('clamps values to be between 0 and max', () => { | ||
const { container: containerNegative } = render(<ProgressBar value={-20} />); | ||
const { container: containerOverMax } = render(<ProgressBar value={150} />); | ||
|
||
const fillNegative = containerNegative.querySelector('.aml__progress-bar-fill'); | ||
const fillOverMax = containerOverMax.querySelector('.aml__progress-bar-fill'); | ||
|
||
expect(fillNegative?.getAttribute('style')).toBe('width: 0%;'); | ||
expect(fillOverMax?.getAttribute('style')).toBe('width: 100%;'); | ||
}); | ||
|
||
it('displays label when provided', () => { | ||
const { getByText } = render(<ProgressBar value={50} label="Loading..." />); | ||
expect(getByText('Loading...')).toBeTruthy(); | ||
}); | ||
|
||
it('does not show percentage by default', () => { | ||
const { queryByText } = render(<ProgressBar value={75} />); | ||
|
||
const percentageElement = queryByText('75%'); | ||
expect(percentageElement).toBeNull(); | ||
}); | ||
|
||
it('hides percentage when showPercentage is false', () => { | ||
const { container } = render(<ProgressBar value={75} showPercentage={false} />); | ||
const percentageElement = container.querySelector('.aml__progress-bar-content-percentage'); | ||
expect(percentageElement).toBeFalsy(); | ||
}); | ||
|
||
it('calculates percentage correctly with custom max value when showPercentage is true', () => { | ||
const { container, getByText } = render(<ProgressBar value={150} max={200} showPercentage={true} />); | ||
const progressFill = container.querySelector('.aml__progress-bar-fill'); | ||
|
||
expect(progressFill?.getAttribute('style')).toBe('width: 75%;'); | ||
expect(getByText('75%')).toBeTruthy(); | ||
}); | ||
|
||
it('displays both label and percentage when both are provided', () => { | ||
const { getByText } = render(<ProgressBar value={50} label="Loading..." showPercentage={true} />); | ||
|
||
expect(getByText('Loading...')).toBeTruthy(); | ||
expect(getByText('50%')).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import React from 'react'; | ||
import './ProgressBar.scss'; | ||
|
||
interface ProgressBarProps { | ||
/** | ||
* Current progress value (0-100) | ||
*/ | ||
value: number; | ||
/** | ||
* Maximum value (defaults to 100) | ||
*/ | ||
max?: number; | ||
/** | ||
* Show percentage text (defaults to true) | ||
*/ | ||
showPercentage?: boolean; | ||
/** | ||
* Optional label text to display above progress bar | ||
*/ | ||
label?: string; | ||
} | ||
|
||
const ProgressBar: React.FC<ProgressBarProps> = ({ | ||
value, | ||
max = 100, | ||
showPercentage = false, | ||
label, | ||
}) => { | ||
const clampedValue = Math.min(Math.max(0, value), max); | ||
const percentage = Math.round((clampedValue / max) * 100); | ||
|
||
return ( | ||
<div className={`aml__progress-bar`}> | ||
<div className={`aml__progress-bar-container`}> | ||
<div | ||
className="aml__progress-bar-fill" | ||
style={{ width: `${percentage}%` }} | ||
/> | ||
<div className={`aml__progress-bar-content`}> | ||
{label && ( | ||
<span className="aml__progress-bar-content-text"> | ||
{label} | ||
</span> | ||
)} | ||
{showPercentage && ( | ||
<span className="aml__progress-bar-content-percentage"> | ||
{percentage}% | ||
</span> | ||
)} | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ProgressBar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import ProgressBar from "../components/ProgressBar/ProgressBar"; | ||
|
||
export default { | ||
title: "ProgressBar", | ||
component: ProgressBar, | ||
parameters: { | ||
layout: "fullscreen", | ||
}, | ||
}; | ||
|
||
export const Default = { | ||
args: { | ||
value: 50, | ||
max: 100, | ||
showPercentage: false, | ||
label: "3 / 20", | ||
size: "md", | ||
}, | ||
decorators: [ | ||
(Story) => ( | ||
<div | ||
style={{ width: "100%", height: "100%", backgroundColor: "#666", padding: "1rem" }} | ||
> | ||
<Story /> | ||
</div> | ||
), | ||
], | ||
}; |