fix: robustify `bind:scrollX/Y` binding (#11655)

- we were scrolling to the given value, which we shouldn't for accessibility reasons (Svelte 4 didn't do it either)
- we need to notify of the value 0 if there's no scroll (https://github.com/sveltejs/svelte/issues/11623#issuecomment-2113495573)
pull/11656/head
Simon H 7 months ago committed by GitHub
parent d288735fa8
commit 110a5a852f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
fix: robustify `bind:scrollX/Y` binding

@ -1,4 +1,4 @@
import { render_effect } from '../../../reactivity/effects.js'; import { effect, render_effect } from '../../../reactivity/effects.js';
import { listen } from './shared.js'; import { listen } from './shared.js';
/** /**
@ -22,7 +22,6 @@ export function bind_window_scroll(type, get_value, update) {
passive: true passive: true
}); });
var latest_value = 0;
var scrolling = false; var scrolling = false;
/** @type {ReturnType<typeof setTimeout>} */ /** @type {ReturnType<typeof setTimeout>} */
@ -30,10 +29,14 @@ export function bind_window_scroll(type, get_value, update) {
var clear = () => { var clear = () => {
scrolling = false; scrolling = false;
}; };
var first = true;
render_effect(() => { render_effect(() => {
latest_value = get_value(); var latest_value = get_value();
if (!scrolling && latest_value != null) { // Don't scroll to the initial value for accessibility reasons
if (first) {
first = false;
} else if (!scrolling && latest_value != null) {
scrolling = true; scrolling = true;
clearTimeout(timeout); clearTimeout(timeout);
if (is_scrolling_x) { if (is_scrolling_x) {
@ -45,6 +48,15 @@ export function bind_window_scroll(type, get_value, update) {
} }
}); });
// Browsers fire the scroll event only if the scroll position is not 0.
// This effect is (almost) guaranteed to run after the scroll event would've fired.
effect(() => {
var value = window[is_scrolling_x ? 'scrollX' : 'scrollY'];
if (value === 0) {
update(value);
}
});
render_effect(() => { render_effect(() => {
return () => { return () => {
removeEventListener('scroll', target_handler); removeEventListener('scroll', target_handler);

Loading…
Cancel
Save