-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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] Improve touch passive event handling #22269
Conversation
f046241
to
761d3ac
Compare
The rule from lighthouse: https://web.dev/uses-passive-event-listeners/. For those who wonder why We push the discussion further in #20990. At least relying more on passive events is a step in the right direction. |
With React 17 change of event delegation, I would expect this problem to surface again facebook/react#6436 |
Bingo #22252 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this correctly we use a pure CSS solution by default where touchAction: none
means scrolling is disabled. However, in iOS this feature isn't supported so we have to fallback to a non-passive scroll listener that calls preventDefault()
?
If that is true then I'd make two suggestions:
-
use feature detection instead of user-agent sniffing
That way new versions of iOS automatically use the better implementation (no JS) once it supports it. And we don't have to rely on compatibility tables which are only useful as an approximation. I know of at least 2 examples in the past year where they were outdated. I'll try to come up with an example for this. Need to find Safari 12 on iOS first. -
Don't check the feature state in the event handler. Seems to me
iOS === true
implies that the event is cancelable
Tested with firefox 51 which does not support let cachedSupportsTouchActionNone;
function doesSupportTouchActionNone() {
if (cachedSupportsTouchActionNone === undefined) {
const element = document.createElement("div");
element.style.touchAction = "none";
document.body.appendChild(element);
cachedSupportsTouchActionNone =
window.getComputedStyle(element).touchAction === "none";
element.parentElement.removeChild(element);
}
return cachedSupportsTouchActionNone;
} It's a bit more involved but also way more robust. Considering the latest safari on iOS does support |
@eps1lon Your assumptions are correct. To answer your points:
I have updated the logic with a new commit, to make it cleaner. |
I don't follow how you come to this conclusion. From what I understand, there are two major elements that reduce its performance win potential.
|
@@ -618,8 +624,7 @@ const Slider = React.forwardRef(function Slider(props, ref) { | |||
}); | |||
|
|||
const handleTouchStart = useEventCallback((event) => { | |||
if (event.cancelable && iOS) { | |||
// Workaround as Safari has partial support for touchAction: 'none'. | |||
if (!touchActionSupport) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just check event.cancelable
? That way we don't accidentally leave this untouch if we change when we add passive listeners or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We get a warning in Chrome if we don't do so.
document this please
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And we should investigate it further. This doesn't seem right.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And we should investigate it further. This doesn't seem right.
Agree, it doesn't seem right, but I don't think that we should care either. Will it make a difference?
I said that I verified it with Firefox 51. Do you have an example where it fails? |
Thanks for the example, I haven't tested, it's ingenious. Honestly, I think that we can keep the iOS check, it sounds good enough for the problem. I believe there are no performance concern #22269 (comment), it's more a matter of preparing the drop of Safari < 13 support. |
ac0af5d
to
bc397e5
Compare
concerns should have been resolved
@@ -126,6 +126,23 @@ const axisProps = { | |||
|
|||
const Identity = (x) => x; | |||
|
|||
// TODO: remove support for Safari < 13. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aside: I really need to get an implementation working with pointer events. With those we don't need touchAction: none if I remember correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would we need to drop the support of older phones if we move to pointer events?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what phones we're supporting. But even our current browserslist would match
@mikhalev-im Thanks for the help |
Fixes #13623
Hope I followed all the guides and didn't miss anything codewise, as this is my first-time contribution