-
-
Notifications
You must be signed in to change notification settings - Fork 32.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Slider work wrong when we config max%step !== 0 #18424
Comments
@nguyetem Thank you for the bug report, I can confirm it. It doesn't behave correctly. At least if we compare it with jQuery UI: https://codepen.io/oliviertassinari/pen/XWWoZzL?editors=1000 or if we set the diff --git a/packages/material-ui/src/Slider/Slider.js b/packages/material-ui/src/Slider/Slider.js
index ad7f144e1..49afa013b 100644
--- a/packages/material-ui/src/Slider/Slider.js
+++ b/packages/material-ui/src/Slider/Slider.js
@@ -83,8 +83,8 @@ function getDecimalPrecision(num) {
return decimalPart ? decimalPart.length : 0;
}
-function roundValueToStep(value, step) {
- const nearest = Math.round(value / step) * step;
+function roundValueToStep(value, step, min) {
+ const nearest = Math.round((value - min) / step) * step + min;
return Number(nearest.toFixed(getDecimalPrecision(step)));
}
@@ -492,7 +492,7 @@ const Slider = React.forwardRef(function Slider(props, ref) {
event.preventDefault();
if (step) {
- newValue = roundValueToStep(newValue, step);
+ newValue = roundValueToStep(newValue, step, min);
}
newValue = clamp(newValue, min, max);
@@ -547,7 +547,7 @@ const Slider = React.forwardRef(function Slider(props, ref) {
let newValue;
newValue = percentToValue(percent, min, max);
if (step) {
- newValue = roundValueToStep(newValue, step);
+ newValue = roundValueToStep(newValue, step, min);
} else {
const marksValues = marks.map(mark => mark.value);
const closestIndex = findClosest(marksValues, newValue);
@@ -946,6 +946,9 @@ Slider.propTypes = {
orientation: PropTypes.oneOf(['horizontal', 'vertical']),
/**
* The granularity with which the slider can step through values. (A "discrete" slider.)
+ * The `min` prop serves as the origin for the valid values.
+ * We recommend (max - min) to be evenly divisible by the step.
+ *
* When step is `null`, the thumb can only be slid onto marks provided with the `marks` prop.
*/
step: PropTypes.number,
diff --git a/packages/material-ui/src/Slider/Slider.test.js b/packages/material-ui/src/Slider/Slider.test.js
index d33596eea..13ebf199f 100644
--- a/packages/material-ui/src/Slider/Slider.test.js
+++ b/packages/material-ui/src/Slider/Slider.test.js
@@ -306,22 +306,37 @@ describe('<Slider />', () => {
key: 'ArrowRight',
};
+ it('should use min as the step origin', () => {
+ const { getByRole } = render(<Slider defaultValue={150} step={100} max={750} min={150} />);
+ const thumb = getByRole('slider');
+ thumb.focus();
+
+ fireEvent.keyDown(document.activeElement, moveRightEvent);
+ expect(thumb).to.have.attribute('aria-valuenow', '250');
+
+ fireEvent.keyDown(document.activeElement, moveLeftEvent);
+ expect(thumb).to.have.attribute('aria-valuenow', '150');
+ });
+
it('should reach right edge value', () => {
const { getByRole } = render(<Slider defaultValue={90} min={6} max={108} step={10} />);
const thumb = getByRole('slider');
thumb.focus();
fireEvent.keyDown(document.activeElement, moveRightEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '100');
+ expect(thumb).to.have.attribute('aria-valuenow', '96');
+
+ fireEvent.keyDown(document.activeElement, moveRightEvent);
+ expect(thumb).to.have.attribute('aria-valuenow', '106');
fireEvent.keyDown(document.activeElement, moveRightEvent);
expect(thumb).to.have.attribute('aria-valuenow', '108');
fireEvent.keyDown(document.activeElement, moveLeftEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '100');
+ expect(thumb).to.have.attribute('aria-valuenow', '96');
fireEvent.keyDown(document.activeElement, moveLeftEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '90');
+ expect(thumb).to.have.attribute('aria-valuenow', '86');
});
it('should reach left edge value', () => {
@@ -329,17 +344,14 @@ describe('<Slider />', () => {
const thumb = getByRole('slider');
thumb.focus();
- fireEvent.keyDown(document.activeElement, moveLeftEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '10');
-
fireEvent.keyDown(document.activeElement, moveLeftEvent);
expect(thumb).to.have.attribute('aria-valuenow', '6');
fireEvent.keyDown(document.activeElement, moveRightEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '20');
+ expect(thumb).to.have.attribute('aria-valuenow', '16');
fireEvent.keyDown(document.activeElement, moveRightEvent);
- expect(thumb).to.have.attribute('aria-valuenow', '30');
+ expect(thumb).to.have.attribute('aria-valuenow', '26');
});
it('should round value to step precision', () => { What do you think about it? Do you want to submit a pull request? :) |
Hey, i've got a chance to work on this. What do you think? |
Hi there! |
@mumac It already does. The component asks for a number. |
Slider work wrong when we config max%step !== 0
Current Behavior 😯
If we configuration slider component like this, the step works wrong way
Expected Behavior 🤔
Expected Step work right way
Steps to Reproduce 🕹
Change step to 50/150/250, it must be max%step === 0 , it will works as expected
The text was updated successfully, but these errors were encountered: