Slider: Adjusts input to enforce min/max values on blur (#40524)

* [cr] adjusts slider input to enfore min/max values on blur

* [cr] additional test for blur action, min/max readability
This commit is contained in:
Coleman Rollins 2021-10-19 09:44:46 -05:00 committed by GitHub
parent e48d77b1eb
commit 70f68289f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 5 deletions

View File

@ -26,4 +26,29 @@ describe('Slider', () => {
expect(wrapper.html()).not.toContain('aria-valuenow="20"'); expect(wrapper.html()).not.toContain('aria-valuenow="20"');
expect(wrapper.html()).not.toContain('aria-valuenow="10"'); expect(wrapper.html()).not.toContain('aria-valuenow="10"');
}); });
it('allows for custom values to be set in the input', () => {
const wrapper = mount(<Slider {...sliderProps} value={10} min={10} max={100} />);
const sliderInput = wrapper.find('input');
sliderInput.simulate('focus');
sliderInput.simulate('change', { target: { value: 50 } });
sliderInput.simulate('blur');
expect(wrapper.html()).toContain('aria-valuenow="50"');
});
it('defaults after blur if input value is outside of range', () => {
const wrapper = mount(<Slider {...sliderProps} value={10} min={10} max={100} />);
const sliderInput = wrapper.find('input');
sliderInput.simulate('focus');
sliderInput.simulate('change', { target: { value: 200 } });
// re-grab to check value is out of range before blur
const sliderInputIncorrect = wrapper.find('input');
expect(sliderInputIncorrect.get(0).props.value).toEqual('200');
sliderInput.simulate('blur');
expect(wrapper.html()).toContain('aria-valuenow="100"');
// re-grab to check value is back inside range
const sliderInputCorrect = wrapper.find('input');
expect(sliderInputCorrect.get(0).props.value).toEqual('100');
});
}); });

View File

@ -1,4 +1,4 @@
import React, { useState, useCallback, ChangeEvent, FunctionComponent } from 'react'; import React, { useState, useCallback, ChangeEvent, FunctionComponent, FocusEvent } from 'react';
import SliderComponent from 'rc-slider'; import SliderComponent from 'rc-slider';
import { cx } from '@emotion/css'; import { cx } from '@emotion/css';
import { Global } from '@emotion/react'; import { Global } from '@emotion/react';
@ -46,9 +46,6 @@ export const Slider: FunctionComponent<SliderProps> = ({
v = 0; v = 0;
} }
v > max && (v = max);
v < min && (v = min);
setSliderValue(v); setSliderValue(v);
if (onChange) { if (onChange) {
@ -59,7 +56,22 @@ export const Slider: FunctionComponent<SliderProps> = ({
onAfterChange(v); onAfterChange(v);
} }
}, },
[max, min, onChange, onAfterChange] [onChange, onAfterChange]
);
// Check for min/max on input blur so user is able to enter
// custom values that might seem above/below min/max on first keystroke
const onSliderInputBlur = useCallback(
(e: FocusEvent<HTMLInputElement>) => {
const v = +e.target.value;
if (v > max) {
setSliderValue(max);
} else if (v < min) {
setSliderValue(min);
}
},
[max, min]
); );
const sliderInputClassNames = !isHorizontal ? [styles.sliderInputVertical] : []; const sliderInputClassNames = !isHorizontal ? [styles.sliderInputVertical] : [];
@ -88,6 +100,7 @@ export const Slider: FunctionComponent<SliderProps> = ({
className={cx(styles.sliderInputField, ...sliderInputFieldClassNames)} className={cx(styles.sliderInputField, ...sliderInputFieldClassNames)}
value={`${sliderValue}`} // to fix the react leading zero issue value={`${sliderValue}`} // to fix the react leading zero issue
onChange={onSliderInputChange} onChange={onSliderInputChange}
onBlur={onSliderInputBlur}
min={min} min={min}
max={max} max={max}
/> />