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

Polyfill onScrollEnd Event in Safari #32427

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

sebmarkbage
Copy link
Collaborator

We added support for onScrollEnd in #26789 but it only works in Chrome and Firefox. Safari still doesn't support scrollend and there's no indication that they will anytime soon so this polyfills it.

While I don't particularly love our synthetic event system this tries to stay within the realm of how our other polyfills work. This implements all onScrollEnd events as a plugin.

The basic principle is to first feature detect the onscrollend DOM property to see if there's native support and otherwise just use the native event.

Then we listen to scroll events and set a timeout. If we don't get any more scroll events before the timeout we fire onScrollEnd. Basically debouncing it. If we're currently pressing down on touch or a mouse then we wait until it is lifted such as if you're scrolling with a finger or using the scrollbars on desktop but isn't currently moving.

If we do get any native events even though we're in polyfilling mode, we use that as an indication to fire the onScrollEnd early.

Part of the motivation is that this becomes extra useful pair for #32422. We also probably need these events to coincide with other gesture related internals so you're better off using our polyfill so they're synced.

@react-sizebot
Copy link

react-sizebot commented Feb 19, 2025

Comparing: 3607f48...399aa22

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.68 kB 6.68 kB = 1.83 kB 1.83 kB
oss-stable/react-dom/cjs/react-dom-client.production.js +0.01% 518.24 kB 518.32 kB +0.02% 92.43 kB 92.45 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.69 kB 6.69 kB = 1.83 kB 1.83 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.47% 570.57 kB 573.25 kB +0.51% 101.56 kB 102.08 kB
facebook-www/ReactDOM-prod.classic.js +0.01% 638.06 kB 638.14 kB +0.03% 112.28 kB 112.31 kB
facebook-www/ReactDOM-prod.modern.js +0.01% 628.38 kB 628.46 kB +0.03% 110.70 kB 110.73 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
facebook-react-native/react-dom/cjs/ReactDOMClient-prod.js +0.49% 543.28 kB 545.95 kB +0.54% 96.42 kB 96.95 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-prod.js +0.49% 548.78 kB 551.46 kB +0.53% 97.50 kB 98.02 kB
facebook-react-native/react-dom/cjs/ReactDOMClient-profiling.js +0.47% 568.14 kB 570.81 kB +0.51% 100.18 kB 100.70 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js +0.47% 570.57 kB 573.25 kB +0.51% 101.56 kB 102.08 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-profiling.js +0.47% 574.08 kB 576.75 kB +0.51% 101.34 kB 101.85 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.production.js +0.46% 585.30 kB 587.98 kB +0.50% 105.12 kB 105.65 kB
oss-experimental/react-dom/cjs/react-dom-profiling.profiling.js +0.43% 626.05 kB 628.72 kB +0.47% 110.30 kB 110.82 kB
facebook-react-native/react-dom/cjs/ReactDOMClient-dev.js +0.32% 993.54 kB 996.71 kB +0.33% 166.85 kB 167.40 kB
facebook-react-native/react-dom/cjs/ReactDOMProfiling-dev.js +0.31% 1,009.87 kB 1,013.04 kB +0.34% 169.68 kB 170.26 kB
oss-experimental/react-dom/cjs/react-dom-client.development.js +0.30% 1,045.95 kB 1,049.12 kB +0.33% 175.18 kB 175.76 kB
oss-experimental/react-dom/cjs/react-dom-profiling.development.js +0.30% 1,062.35 kB 1,065.52 kB +0.32% 178.03 kB 178.61 kB
oss-experimental/react-dom/cjs/react-dom-unstable_testing.development.js +0.30% 1,062.87 kB 1,066.04 kB +0.32% 178.90 kB 179.47 kB

Generated by 🚫 dangerJS against dead6ae

@sebmarkbage
Copy link
Collaborator Author

Note that at one point in the past the scroll event wasn't firing during momentum scroll in Safari. Then you needed to use a requestAnimationFrame loop to track when scroll position stopped updating. This doesn't appear to be the case any more, using debounced scroll seems enough.

Enabled in native and test-renderer since they shouldn't affect them anyway.
Makes it easier to see that it's safe to ship.
@sebmarkbage
Copy link
Collaborator Author

There's some movement in Safari. It's part of the roadmap for 2025. https://webkit.org/blog/16458/announcing-interop-2025/#scrollend-event

But we still need to polyfill for now and for older versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed React Core Team Opened by a member of the React Core Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants