Skip to content
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] Ends are unreachable with mouse drags #1360

Closed
SimeonRolev opened this issue Jan 27, 2025 · 6 comments · Fixed by #1411
Closed

[Slider] Ends are unreachable with mouse drags #1360

SimeonRolev opened this issue Jan 27, 2025 · 6 comments · Fixed by #1411
Assignees
Labels
bug 🐛 Something doesn't work component: slider This is the name of the generic UI component, not the React module!

Comments

@SimeonRolev
Copy link

Bug report

Current behavior

Drag a Slider to one of its ends. Value is properly set to 0 or 100, but the Slider.Thumb doesn't get positioned at the very start/end of the Slider.Track (its inset-inline-start CSS property is set to 0.4242% or 99.4242%, for example). A proper positioning is only achievable with a quick drag. It's more obvious with wider sliders or multiple sliders one under the other.

Screencast.from.27.01.2025.19.06.21.webm

Expected behavior

The positioning of the thumb should reflect the value passed to the onValueChange(value, event) - a value of 0 / 100 positions the Slider.Thumb at inset-inline-start: 0% / 100%; without the need of a quick mouse drag.

Reproducible example

https://base-ui.com/react/components/slider

Base UI version

^1.0.0-alpha.5

Which browser are you using?

Chrome

@github-actions github-actions bot added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jan 27, 2025
@SimeonRolev SimeonRolev changed the title Ends are unreachable Slider: ends are unreachable Jan 27, 2025
@mj12albert mj12albert changed the title Slider: ends are unreachable [Slider] Ends are unreachable with mouse drags Jan 28, 2025
@mj12albert mj12albert self-assigned this Jan 28, 2025
@mj12albert mj12albert added the component: slider This is the name of the generic UI component, not the React module! label Jan 28, 2025
@mj12albert
Copy link
Member

mj12albert commented Jan 28, 2025

Thanks for reporting this @SimeonRolev

This would be caused by #1219, I think we need to round the position values when the pointer is released

@SimeonRolev
Copy link
Author

SimeonRolev commented Jan 28, 2025

@mj12albert That's what I initially thought of as a workaround and I gave it a shot yesterday, utilizing the onValueCommitted callback. As the min/max values of the Slider might not be 0 to 100, I parsed the value of the thumbNode.style.insetInlineStart css property instead to determine whether we are close to an edge and re-adjust the Slider.Thumb only in that case to avoid re-adjusting on every mouse up. This approximation can be improved for example by using the min, max and step values properly, instead of just comparing <1 || >99, but you get the point.

Unfortunately, I don't think it's optimal. A user sets a slider's value during a mouse drag and seeing the slider re-adjust on its own upon mouse release is awkward - even if it happens only at the edges. Makes you not trust the component - did it only glitch visually or did it slightly tweak my value, too?

const MySlider = (props) => {
    const ref = useRef(null);

    const onValueCommitted = (value, event) => {
        handleEdges();
        return props.onValueCommitted?.(value, event);
    };

    const handleEdges = () => {
        if (props.orientation === 'vertical') return;

        const thumbNode = ref.current.querySelector('.thumb');
        if (!thumbNode) return;

        const cssValue = thumbNode.style.insetInlineStart;
        if (cssValue.endsWith('%')) {
            const value = Number(cssValue.substring(0, cssValue.length - 1)); // remove % sign
            if (value < 1) thumbNode.style.insetInlineStart = '0%';
            if (value > 99) thumbNode.style.insetInlineStart = '100%';
        }
    };

    return (
        <div ref={ref}>
            <Slider.Root
                {...props}
                onValueCommitted={onValueCommitted}
            >
                <Slider.Control>
                    <Slider.Track>
                        <Slider.Thumb className='thumb' />
                    </Slider.Track>
                </Slider.Control>
            </Slider.Root>
        </div>
    );
};

@SimeonRolev
Copy link
Author

One more example of the UI not respecting the steps of the slider properly:
<Slider onValueChange={v => console.log('Value', v)} min={0} max={10} step={2} />

Screencast.from.28.01.2025.11.38.09.webm

@oliviertassinari
Copy link
Member

oliviertassinari commented Jan 29, 2025

Is this a regression from https://mui.com/base-ui/react-slider/? Are we missing a test case from MUI Base?

@mj12albert
Copy link
Member

Is this a regression from https://mui.com/base-ui/react-slider/? Are we missing a test case from MUI Base?

It was caused by #1219 which changed the thumb styles to be based on the pointer position instead of being always derived from the value in MUI Base (which is always rounded/clamped) 🙇

@mj12albert mj12albert moved this from Backlog to In progress in Base UI Feb 4, 2025
@mj12albert mj12albert added bug 🐛 Something doesn't work and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Feb 4, 2025
@mj12albert
Copy link
Member

@SimeonRolev If you would like to test the fix locally in the mean time:

npm install https://pkg.csb.dev/mui/base-ui/commit/6599a23d/@base-ui-components/react

@github-project-automation github-project-automation bot moved this from In progress to Done in Base UI Feb 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something doesn't work component: slider This is the name of the generic UI component, not the React module!
Projects
Archived in project
Development

Successfully merging a pull request may close this issue.

3 participants