diff --git a/packages/grafana-ui/src/components/Slider/Slider.test.tsx b/packages/grafana-ui/src/components/Slider/Slider.test.tsx
index f688f546508..d4274a8dc4b 100644
--- a/packages/grafana-ui/src/components/Slider/Slider.test.tsx
+++ b/packages/grafana-ui/src/components/Slider/Slider.test.tsx
@@ -26,4 +26,29 @@ describe('Slider', () => {
expect(wrapper.html()).not.toContain('aria-valuenow="20"');
expect(wrapper.html()).not.toContain('aria-valuenow="10"');
});
+
+ it('allows for custom values to be set in the input', () => {
+ const wrapper = mount();
+ 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();
+ 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');
+ });
});
diff --git a/packages/grafana-ui/src/components/Slider/Slider.tsx b/packages/grafana-ui/src/components/Slider/Slider.tsx
index 329105ff912..4cc36a31426 100644
--- a/packages/grafana-ui/src/components/Slider/Slider.tsx
+++ b/packages/grafana-ui/src/components/Slider/Slider.tsx
@@ -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 { cx } from '@emotion/css';
import { Global } from '@emotion/react';
@@ -46,9 +46,6 @@ export const Slider: FunctionComponent = ({
v = 0;
}
- v > max && (v = max);
- v < min && (v = min);
-
setSliderValue(v);
if (onChange) {
@@ -59,7 +56,22 @@ export const Slider: FunctionComponent = ({
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) => {
+ const v = +e.target.value;
+
+ if (v > max) {
+ setSliderValue(max);
+ } else if (v < min) {
+ setSliderValue(min);
+ }
+ },
+ [max, min]
);
const sliderInputClassNames = !isHorizontal ? [styles.sliderInputVertical] : [];
@@ -88,6 +100,7 @@ export const Slider: FunctionComponent = ({
className={cx(styles.sliderInputField, ...sliderInputFieldClassNames)}
value={`${sliderValue}`} // to fix the react leading zero issue
onChange={onSliderInputChange}
+ onBlur={onSliderInputBlur}
min={min}
max={max}
/>