Skip to content

fix(router-core): stop forcing history.scrollRestoration to 'manual' - #8347

Open
Ishkirat-Singh wants to merge 1 commit into
TanStack:mainfrom
Ishkirat-Singh:fix/scroll-restoration-keep-browser-default
Open

fix(router-core): stop forcing history.scrollRestoration to 'manual'#8347
Ishkirat-Singh wants to merge 1 commit into
TanStack:mainfrom
Ishkirat-Singh:fix/scroll-restoration-keep-browser-default

Conversation

@Ishkirat-Singh

@Ishkirat-Singh Ishkirat-Singh commented Sep 10, 2026

Copy link
Copy Markdown

🎯 Changes

Fixes #7956 (follow-up to #7815).

setupScrollRestoration still set history.scrollRestoration = 'manual' whenever scrollRestoration: true. Forcing manual mode turns off the browser's native pre-paint restore, which is what iOS Safari's swipe-back preview and Chrome's hard refresh rely on: Safari repainted at the wrong offset after the gesture, and Chrome painted at the top and snapped down a frame later. The router's own restore runs post-paint in the onRendered subscriber; it still runs, still corrects the window position and still restores individual scroll containers, none of which depend on manual mode.

This PR removes the assignment and leaves history.scrollRestoration on the browser default. As discussed in the issue it is a plain removal rather than an option: no case was found where 'manual' restores better than native restore plus the router's corrector, so an opt-in would only preserve the regression path.

  • packages/router-core/src/scroll-restoration.ts: drop the history.scrollRestoration = 'manual' assignment.
  • packages/router-core/tests/scroll-restoration.test.ts: the setup test now asserts that scrollRestoration stays 'auto', with a comment explaining why.
  • Changeset for @tanstack/router-core (patch).

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with the relevant test commands, or tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

Summary by CodeRabbit

  • Bug Fixes
    • Improved scroll restoration during browser navigation and hard refreshes.
    • Preserved the browser’s native scroll restoration before the page’s first paint, improving swipe-back previews and preventing visible scroll jumps.
    • Continued restoring scroll positions for individual containers after navigation.

setupScrollRestoration forced history.scrollRestoration to 'manual'. That
setting only governs the window, and the router restores the window after
paint (in the onRendered subscriber) while the browser's native restoration
runs before it: forcing manual mode made iOS Safari's swipe-back preview
land at the wrong offset and made Chrome paint at the top and snap down
after a hard refresh. Per-element restoration and the router's own window
correction are unaffected by the flag, so stop changing it.

Closes TanStack#7956
@coderabbitai

coderabbitai Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: 0e79cb26-6c45-4b3b-8a73-32d5623dd1b8

📥 Commits

Reviewing files that changed from the base of the PR and between 6494e75 and d18ca56.

📒 Files selected for processing (3)
  • .changeset/scroll-restoration-browser-default.md
  • packages/router-core/src/scroll-restoration.ts
  • packages/router-core/tests/scroll-restoration.test.ts
💤 Files with no reviewable changes (1)
  • packages/router-core/src/scroll-restoration.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.


📝 Walkthrough

Walkthrough

The router no longer forces history.scrollRestoration to 'manual'. Browser-native restoration remains enabled, while router-managed tracking and restoration continue unchanged. Tests and release metadata now reflect this behavior.

Changes

Scroll restoration behavior

Layer / File(s) Summary
Preserve browser scroll restoration
packages/router-core/src/scroll-restoration.ts, packages/router-core/tests/scroll-restoration.test.ts, .changeset/scroll-restoration-browser-default.md
The router no longer assigns 'manual' to history.scrollRestoration. The test expects 'auto', and the changeset records the patch release.

Priority: ➖ Normal

Estimated code review effort: 1 (Trivial) | ~5 minutes

Severity of issue fixed: Medium

Suggested reviewers: schiller-manuel

Merge Risk: ⚪ Minimal · up to d18ca

This PR removes the conflicting manual scroll setting and keeps native browser restoration enabled. No actionable merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR removes the forced 'manual' assignment and preserves the existing restoration logic. However, linked issue #7956 also identifies moving router scroll work to a pre-paint layout effect as part o… Implement the linked issue's required pre-paint router scroll work, including PUSH scroll-to-top and traversal restoration, or update the issue linkage and scope to confirm that this PR addresses only the history.scrollRestoration assignmen…
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: stopping the forced manual scroll restoration setting.
Description check ✅ Passed The description includes the required Changes, Checklist, and Release Impact sections. It explains the motivation, implementation, testing status, and changeset.
Out of Scope Changes check ✅ Passed The changes are limited to removing the forced history setting, updating the related test, and adding the required router-core changeset. These changes align with the stated objectives and contain no …
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 1…
Full details: Linked Issues check

Explanation

The PR removes the forced 'manual' assignment and preserves the existing restoration logic. However, linked issue #7956 also identifies moving router scroll work to a pre-paint layout effect as part of the complete fix, and this PR does not implement that change.

Resolution

Implement the linked issue's required pre-paint router scroll work, including PUSH scroll-to-top and traversal restoration, or update the issue linkage and scope to confirm that this PR addresses only the history.scrollRestoration assignment.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

history.scrollRestoration should never be changed from 'auto' — 'manual' regresses iOS Safari swipe-back and Chrome refresh (follow-up to #7815)

1 participant