From d126c1a4601ed5dc5925836606923ed0e88504e9 Mon Sep 17 00:00:00 2001
From: ClaraTschamon <103147059+ClaraTschamon@users.noreply.github.com>
Date: Wed, 11 Sep 2024 10:20:13 +0200
Subject: [PATCH] feat(slider): enable change of slider value though a prop
(#210)
---
src/components/Slider/Slider.stories.tsx | 1 +
src/components/Slider/Slider.test.tsx | 10 ++++++++++
src/components/Slider/Slider.tsx | 25 +++++++++++++++++-------
3 files changed, 29 insertions(+), 7 deletions(-)
diff --git a/src/components/Slider/Slider.stories.tsx b/src/components/Slider/Slider.stories.tsx
index 43b26e4..525db12 100644
--- a/src/components/Slider/Slider.stories.tsx
+++ b/src/components/Slider/Slider.stories.tsx
@@ -42,6 +42,7 @@ WithCustomMinAndMax.args = {
export const WithLowerAndUpperBound = Template.bind({});
WithLowerAndUpperBound.args = {
variant: 'boundary',
+ value: 45,
min: 10,
max: 90,
lowerBoundText: 'Lower bound',
diff --git a/src/components/Slider/Slider.test.tsx b/src/components/Slider/Slider.test.tsx
index 971d9cc..8db9dc1 100644
--- a/src/components/Slider/Slider.test.tsx
+++ b/src/components/Slider/Slider.test.tsx
@@ -122,5 +122,15 @@ describe('The Slider component', () => {
expect(screen.getByRole('tooltip')).toBeInTheDocument();
});
+
+ it('updates the slider value when the external value prop changes', () => {
+ const { rerender } = render();
+
+ expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow', '30');
+
+ rerender();
+
+ expect(screen.getByRole('slider')).toHaveAttribute('aria-valuenow', '70');
+ });
});
});
diff --git a/src/components/Slider/Slider.tsx b/src/components/Slider/Slider.tsx
index de316ed..bdfa7b6 100644
--- a/src/components/Slider/Slider.tsx
+++ b/src/components/Slider/Slider.tsx
@@ -1,5 +1,5 @@
import { StyleProps, useMediaQuery } from '@chakra-ui/react';
-import React, { useMemo, useState } from 'react';
+import React, { useEffect, useMemo, useState } from 'react';
import {
Slider,
SliderTrack,
@@ -15,6 +15,7 @@ import CustomSliderThumb from './CustomSliderThumb';
export interface SliderProps extends StyleProps {
variant?: 'default' | 'boundary';
defaultValue?: number;
+ value?: number;
ariaLabel: string;
min?: number;
max?: number;
@@ -27,6 +28,7 @@ export interface SliderProps extends StyleProps {
export const BoemlySlider: React.FC = ({
variant = 'default',
defaultValue,
+ value,
ariaLabel,
min = 0,
max = 100,
@@ -39,16 +41,25 @@ export const BoemlySlider: React.FC = ({
const [isMobile] = useMediaQuery(BREAKPOINT_MD_QUERY);
const initialValue = useMemo(
- () => defaultValue ?? min + (max - min) / 2,
- [defaultValue, min, max]
+ () => value ?? defaultValue ?? min + (max - min) / 2,
+ [defaultValue, min, max, value]
);
+
const [sliderValue, setSliderValue] = useState(initialValue);
const [inputValue, setInputValue] = useState(initialValue.toString());
- const sliderOnChange = (value: number) => {
- setSliderValue(value);
- setInputValue(value.toString());
- onChange(value);
+ // Update internal sliderValue when the external value prop changes
+ useEffect(() => {
+ if (value !== undefined) {
+ setSliderValue(value);
+ setInputValue(value.toString());
+ }
+ }, [value]);
+
+ const sliderOnChange = (newValue: number) => {
+ setSliderValue(newValue);
+ setInputValue(newValue.toString());
+ onChange(newValue);
};
const inputOnChange = (event: React.ChangeEvent) => {