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) => {