Skip to content

Commit e2af0e7

Browse files
committed
Reusable Range slider
1 parent 03e2791 commit e2af0e7

File tree

2 files changed

+74
-16
lines changed

2 files changed

+74
-16
lines changed

src/components/Product/ProductFilters.component.tsx

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Dispatch, SetStateAction } from 'react';
22
import { Product, ProductType } from '@/types/product';
33
import Button from '@/components/UI/Button.component';
44
import Checkbox from '@/components/UI/Checkbox.component';
5+
import RangeSlider from '@/components/UI/RangeSlider.component';
56

67
interface ProductFiltersProps {
78
selectedSizes: string[];
@@ -85,22 +86,16 @@ const ProductFilters = ({
8586

8687
<div className="mb-8">
8788
<h3 className="font-semibold mb-4">PRIS</h3>
88-
<label htmlFor="price-range" className="sr-only">Pris</label>
89-
<input
90-
id="price-range"
91-
type="range"
92-
min="0"
93-
max="1000"
94-
value={priceRange[1]}
95-
onChange={(e) =>
96-
setPriceRange([priceRange[0], parseInt(e.target.value)])
97-
}
98-
className="w-full cursor-pointer"
99-
/>
100-
<div className="flex justify-between mt-2">
101-
<span>kr {priceRange[0]}</span>
102-
<span>kr {priceRange[1]}</span>
103-
</div>
89+
<RangeSlider
90+
id="price-range"
91+
label="Pris"
92+
min={0}
93+
max={1000}
94+
value={priceRange[1]}
95+
startValue={priceRange[0]}
96+
onChange={(value) => setPriceRange([priceRange[0], value])}
97+
formatValue={(value) => `kr ${value}`}
98+
/>
10499
</div>
105100

106101
<div className="mb-8">
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { ChangeEvent } from 'react';
2+
3+
interface IRangeSliderProps {
4+
id: string;
5+
label: string;
6+
min: number;
7+
max: number;
8+
value: number;
9+
onChange: (value: number) => void;
10+
startValue?: number;
11+
formatValue?: (value: number) => string;
12+
}
13+
14+
/**
15+
* A reusable range slider component with labels
16+
* @function RangeSlider
17+
* @param {string} id - Unique identifier for the slider
18+
* @param {string} label - Accessible label for the slider
19+
* @param {number} min - Minimum value of the range
20+
* @param {number} max - Maximum value of the range
21+
* @param {number} value - Current value of the slider
22+
* @param {function} onChange - Handler for when the slider value changes
23+
* @param {number} startValue - Optional starting value to display (defaults to min)
24+
* @param {function} formatValue - Optional function to format the displayed values
25+
* @returns {JSX.Element} - Rendered component
26+
*/
27+
const RangeSlider = ({
28+
id,
29+
label,
30+
min,
31+
max,
32+
value,
33+
onChange,
34+
startValue = min,
35+
formatValue = (val: number) => val.toString(),
36+
}: IRangeSliderProps) => {
37+
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
38+
onChange(parseInt(e.target.value));
39+
};
40+
41+
return (
42+
<div>
43+
<label htmlFor={id} className="sr-only">
44+
{label}
45+
</label>
46+
<input
47+
id={id}
48+
type="range"
49+
min={min}
50+
max={max}
51+
value={value}
52+
onChange={handleChange}
53+
className="w-full cursor-pointer"
54+
/>
55+
<div className="flex justify-between mt-2">
56+
<span>{formatValue(startValue)}</span>
57+
<span>{formatValue(value)}</span>
58+
</div>
59+
</div>
60+
);
61+
};
62+
63+
export default RangeSlider;

0 commit comments

Comments
 (0)