react icon indicating copy to clipboard operation
react copied to clipboard

[UX Improvement] Disable mouse wheel behavior on number type inputs

Open Jule- opened this issue 3 years ago • 9 comments

There is annoying behaviour that should not exist IMHO for UX's sake: when you scroll on an <input type="number"> you can change input when you have the focus on it which is not user-friendly at all since the mouse wheel is almost exclusively used for scrolling page. As a result, people are typing a value, then trying to scroll further for another input and then changing the input value without even noticing for the majority.

I don't know what is implemented in React that changes how it is handled in most browsers. I have tried to track down the event which is modifying the input without success. But if you try vanilla javascript in, let's say, Chrome then you don't have this ugly behaviour. :man_shrugging:

For illustration purposes:

  • React behaviour: https://codesandbox.io/s/silly-feynman-ic8f9p
  • Vanilla behaviour: https://codesandbox.io/s/laughing-fog-rkrc6s

Another reference: https://stackoverflow.com/questions/68260072/why-can-we-update-a-value-of-a-number-input-using-mouse-wheel

Can someone explain why and where in the code wheel is changing the input? Or why it is not like that in vanilla JS (for most browsers)?

And maybe deciding to change the default behaviour to something more user-friendly could be discussed?

Jule- avatar Jul 25 '22 14:07 Jule-

It's NOT only stupid thing in react.

Here is some (simplified) code from a project.

<div
  // React uses `focusIn/focusOut` under the hood
  onFocus={() => setPauseOnHover(true)}
  onBlur={() => setPauseOnHover(false)}
/>

And a strange thing is happening with onMouseLeave

design-principles avatar Jul 25 '22 16:07 design-principles

I want to work on this issue

shikhar13012001 avatar Aug 01 '22 06:08 shikhar13012001

For React.js, I was able to fix the issue by adding "onWheel={(e) => e.target.blur()}" inside the input tag.

hanswang123456 avatar Aug 06 '22 20:08 hanswang123456

Yeah, it is a workaround I use too. But still, it is lousy UX because it will unfocus the input field while scrolling which is not what users expect. It does not happen for other inputs so why for number one?!

Jule- avatar Aug 07 '22 11:08 Jule-

I want to mention, that react rendering affects also inputs that are draw outside the React component.

https://codesandbox.io/s/wheel-problem-5nz2b5?file=/src/index.js:110-282

vvscode avatar Aug 29 '22 08:08 vvscode

@vvscode indeed, as exposed in my first codesandbox, but I forgot to mention it clearly. Thanks for mentioning that annoying side effect!

Jule- avatar Aug 29 '22 15:08 Jule-

It's possible to get correct behaviour with adding event to the ref, but if you are using forwardRef it's became tricky.

const domRef = React.useRef<HTMLInputElement>();
React.useEffect(() => {
     const preventInputScroll = (e: WheelEvent) => e.preventDefault();
     domRef.current?.addEventListener('wheel', preventInputScroll);
     return () => {
         domRef.current?.removeEventListener('wheel', preventInputScroll);
     };
});
return (<input type='number' ref='domRef' />);

qvantor avatar Sep 07 '22 13:09 qvantor

document.body.addEventListener("wheel", (ev) => {
    const target = ev.composedPath()[0] as HTMLElement;
    if (target.matches('input[type="number"]')) {
        target.blur();
    }
});

solves the problem globally (including shadow DOM)

vvscode avatar Sep 08 '22 09:09 vvscode

@vvscode Thanks for the code snippets but unfortunately this is still a lousy behaviour, not a real transparent solution. And thus this cannot be an excuse to not fix this issue.

@qvantor Thanks for the code snippet too but last time I checked calling preventDefault() have the side effect of preventing the user from scrolling when the input is focused, again not a proper fix but could be a lousy workaround for some people though.

@shikhar13012001 any news about your help proposal or this has just been ignored?

Jule- avatar Sep 08 '22 10:09 Jule-

may not be a React bug, all you need to reproduce this is a passive wheel listener attached to some element (does not have to be the input element)

https://codesandbox.io/s/friendly-browser-ueyekx

yihongang avatar Dec 12 '22 14:12 yihongang

Hey, I want to work on your issues try to give me this UX improvement . thank you !!

kumarvishal2002 avatar Oct 14 '23 06:10 kumarvishal2002