Skip to content

Commit 77a1a73

Browse files
authored
allow disableScrollHandling() to be called in afterNavigate (#4948)
* allow disableScrollHandling to be called in afterNavigate - fixes #3220 * fix tests * remove .only * format
1 parent b2a8c5c commit 77a1a73

File tree

7 files changed

+60
-20
lines changed

7 files changed

+60
-20
lines changed

.changeset/polite-files-explain.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
allow disableScrollHandling to be called in afterNavigate

packages/kit/src/runtime/client/client.js

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,9 @@ export function create_client({ target, session, base, trailing_slash }) {
232232
* @param {string[]} redirect_chain
233233
* @param {boolean} no_cache
234234
* @param {{hash?: string, scroll: { x: number, y: number } | null, keepfocus: boolean, details: { replaceState: boolean, state: any } | null}} [opts]
235+
* @param {() => void} [callback]
235236
*/
236-
async function update(url, redirect_chain, no_cache, opts) {
237+
async function update(url, redirect_chain, no_cache, opts, callback) {
237238
const intent = get_navigation_intent(url);
238239

239240
const current_token = (token = {});
@@ -360,7 +361,6 @@ export function create_client({ target, session, base, trailing_slash }) {
360361
load_cache.promise = null;
361362
load_cache.id = null;
362363
autoscroll = true;
363-
updating = false;
364364

365365
if (navigation_result.props.page) {
366366
page = navigation_result.props.page;
@@ -369,7 +369,9 @@ export function create_client({ target, session, base, trailing_slash }) {
369369
const leaf_node = navigation_result.state.branch[navigation_result.state.branch.length - 1];
370370
router_enabled = leaf_node?.module.router !== false;
371371

372-
return true;
372+
if (callback) callback();
373+
374+
updating = false;
373375
}
374376

375377
/** @param {import('./types').NavigationResult} result */
@@ -387,12 +389,12 @@ export function create_client({ target, session, base, trailing_slash }) {
387389
hydrate: true
388390
});
389391

390-
started = true;
391-
392392
if (router_enabled) {
393393
const navigation = { from: null, to: new URL(location.href) };
394394
callbacks.after_navigate.forEach((fn) => fn(navigation));
395395
}
396+
397+
started = true;
396398
}
397399

398400
/**
@@ -978,18 +980,22 @@ export function create_client({ target, session, base, trailing_slash }) {
978980
});
979981
}
980982

981-
const completed = await update(normalized, redirect_chain, false, {
982-
scroll,
983-
keepfocus,
984-
details
985-
});
986-
987-
if (completed) {
988-
const navigation = { from, to: normalized };
989-
callbacks.after_navigate.forEach((fn) => fn(navigation));
983+
await update(
984+
normalized,
985+
redirect_chain,
986+
false,
987+
{
988+
scroll,
989+
keepfocus,
990+
details
991+
},
992+
() => {
993+
const navigation = { from, to: normalized };
994+
callbacks.after_navigate.forEach((fn) => fn(navigation));
990995

991-
stores.navigating.set(null);
992-
}
996+
stores.navigating.set(null);
997+
}
998+
);
993999
}
9941000

9951001
/**
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<script>
2+
import { afterNavigate, disableScrollHandling } from '$app/navigation';
3+
4+
afterNavigate(() => {
5+
disableScrollHandling();
6+
document.getElementById('abcde')?.scrollIntoView();
7+
});
8+
</script>
9+
10+
<div style="height: 180vh; background-color: hotpink;">They (don't) see me...</div>
11+
<div style="height: 180vh; background-color: peru;">
12+
<p id="go-to-element">The browser scrolls to me</p>
13+
</div>
14+
<p id="abcde" style="height: 180vh; background-color: hotpink;">I take precedence</p>
15+
<div />
16+
17+
<a href="/anchor-with-manual-scroll/anchor-afternavigate?x=y#go-to-element">reload me</a>

packages/kit/test/apps/basics/src/routes/anchor-with-manual-scroll/index.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<h1>Welcome to a test project</h1>
2-
<a href="/anchor-with-manual-scroll/anchor#go-to-element">Anchor demo</a>
2+
<a href="/anchor-with-manual-scroll/anchor-onmount#go-to-element">Anchor demo</a>
33

44
<style>
55
:global(body) {

packages/kit/test/apps/basics/test/test.js

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,19 @@ test.describe('Scrolling', () => {
259259
page,
260260
in_view
261261
}) => {
262-
await page.goto('/anchor-with-manual-scroll/anchor#go-to-element');
262+
await page.goto('/anchor-with-manual-scroll/anchor-onmount#go-to-element');
263+
expect(await in_view('#abcde')).toBe(true);
264+
});
265+
266+
test('url-supplied anchor is ignored with afterNavigate() scrolling on direct page load', async ({
267+
page,
268+
in_view,
269+
clicknav
270+
}) => {
271+
await page.goto('/anchor-with-manual-scroll/anchor-afternavigate#go-to-element');
272+
expect(await in_view('#abcde')).toBe(true);
273+
274+
await clicknav('[href="/anchor-with-manual-scroll/anchor-afternavigate?x=y#go-to-element"]');
263275
expect(await in_view('#abcde')).toBe(true);
264276
});
265277

@@ -270,7 +282,7 @@ test.describe('Scrolling', () => {
270282
in_view
271283
}) => {
272284
await page.goto('/anchor-with-manual-scroll');
273-
await clicknav('[href="/anchor-with-manual-scroll/anchor#go-to-element"]');
285+
await clicknav('[href="/anchor-with-manual-scroll/anchor-onmount#go-to-element"]');
274286
if (javaScriptEnabled) expect(await in_view('#abcde')).toBe(true);
275287
else expect(await in_view('#go-to-element')).toBe(true);
276288
});

packages/kit/types/ambient.d.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ declare module '$app/env' {
8888
*/
8989
declare module '$app/navigation' {
9090
/**
91-
* If called when the page is being updated following a navigation (in `onMount` or an action, for example), this disables SvelteKit's built-in scroll handling.
91+
* If called when the page is being updated following a navigation (in `onMount` or `afterNavigate` or an action, for example), this disables SvelteKit's built-in scroll handling.
9292
* This is generally discouraged, since it breaks user expectations.
9393
*/
9494
export function disableScrollHandling(): void;

0 commit comments

Comments
 (0)