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

[number-field] Provide an option to prevent scrolling from changing the value #6158

Closed
sissbruecker opened this issue Jul 13, 2023 · 8 comments · Fixed by #6362
Closed

[number-field] Provide an option to prevent scrolling from changing the value #6158

sissbruecker opened this issue Jul 13, 2023 · 8 comments · Fixed by #6362

Comments

@sissbruecker
Copy link
Contributor

Describe your motivation

In certain browsers (Chrome, Safari), scrolling over an input with type="number" increases or decreases the value. This is the native behavior of the browser, and not something that is specifically implemented in our components. This behavior is problematic as it results in a questionable UX that can confuse users (#919) and makes our components work inconsistently across browsers.

Describe the solution you'd like

As mentioned in the linked issue, there are no simple workarounds that wouldn't introduce other side effects. The least intrusive solution seems to be to blur the field when it is scrolled over. As this still has side-effects, we should provide this as an opt-in feature that can be enabled by setting an attribute, such as blur-on-scroll.

Describe alternatives you've considered

An alternative is to prevent scrolling on the field, however that has the side effect that the whole page doesn't scroll either when the cursor is over the field.

Additional context

Refactoring the number field components to use type="text" would resolve this problem as well: #3102

@rolfsmeds
Copy link
Contributor

Can you describe the side-effects you have in mind that would need to be warned about in the javadoc/jsdoc?

@sissbruecker
Copy link
Contributor Author

That was maybe phrased badly, as it's not so much a side-effect but a direct effect. My point was that blurring the field on scroll is not ideal UX either, for example when a user briefly scrolls away to look something up on the page, before continuing to fill out the field. At that point the field is not focused anymore and needs to be focused again, which is inconvenient. Also confusing maybe, as that would only happen if you start scrolling directly over the field, but not when starting to scroll next to it.

@rolfsmeds
Copy link
Contributor

Would it be possible to automatically re-focus the field once the pointer has mouseout'ed?

@sissbruecker
Copy link
Contributor Author

Maybe. However another concern might be that removing focus from the field would also trigger validation (at least for the web component), which would be even more confusing if the focus would be restored.

@rolfsmeds
Copy link
Contributor

If it's possible to detect when the workaround is no longer needed, I wonder if we could set pointer-events:none on it instead of blurring? That should avoid any side-effects.

@vursen
Copy link
Contributor

vursen commented Aug 15, 2023

Here are a few observations from our internal testing:


Mac OS + Chrome

The spinning-on-scroll behavior only activates when there is a wheel listener added to the input or any of its ancestor elements. When the listener is added directly to the input, the page scroll is prevented, otherwise not.

Mac OS + Safari

The spinning-on-scroll behavior only activates when there is a wheel listener. When the listener is added directly to the input, the page scroll is prevented, otherwise not.

Mac OS + Firefox

The spinning-on-scroll behavior isn't observed even if there is a wheel listener. The page scroll is not prevented.

Windows + Firefox

The spinning-on-scroll behavior is observed regardless of anything. The page scroll is prevented.

Windows + Chrome

Same as on Mac OS, the spinning-on-scroll behavior only activates when there is a wheel listener. When the listener is added directly to the input, the page scroll is prevented, otherwise not.

Windows + Edge

The spinning-on-scroll behavior is observed by default. The page scroll is not prevented. Adding a wheel listener directly to the input prevents the page scroll.


Also, calling preventDefault() for the wheel event consistently prevents the spinning-on-scroll behavior across all browsers. However, as a side-effect, it also consistently prevents the page scroll when the pointer is over the field.

@vursen
Copy link
Contributor

vursen commented Aug 15, 2023

If it's possible to detect when the workaround is no longer needed, I wonder if we could set pointer-events:none on it instead of blurring? That should avoid any side-effects.

Apart from setting pointer-event, this solution will have to undo the browser's increment action. The only way to do this is to reset the input element's value property to the original value before the increment. However, this will result in losing text selection and bad input.

While there should be a workaround to restore text selection, restoring bad input is a huge problem. I'm not sure if it's even feasible. In order to restore it, you need to know what exactly the user entered. The problem is that the native type="number" don't provide access to what the user entered if it's invalid. Their value property just returns an empty string in that case.


EDIT: Instead of trying to undo the increment action, it's possible to prevent the first wheel event. However, this doesn't work reliably on Windows + Firefox: the browser still manages to increment or decrement the value occasionally.

@vursen
Copy link
Contributor

vursen commented Aug 15, 2023

All things considered, the solution that prevents default for wheel events seems like the least problematic to me. To minimize the impact of page scroll prevention, it should be enough to call preventDefault() for wheel events only while the field is focused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants