scroll: smooth only for same-route hash, restore savedPosition

Three rules:
- Browser back/forward → restore exact scroll y (preserves shop ⇄
  product round-trips, fixes regression).
- Same-route hash nav (clicking Bundles while on home) → smooth.
- Cross-route hash nav (/shop → /#bundles) → instant.

Removed the global `html { scroll-behavior: smooth }` so plain
forward navigations and back/forward jumps stay instant.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dorian
2026-05-03 16:16:32 +01:00
parent 4f6c697bc6
commit eefaa06995
3 changed files with 16 additions and 10 deletions

View File

@@ -160,15 +160,21 @@ const router = createRouter({
routes,
// Scroll rules:
// • Browser back/forward → restore the previous scroll y so
// /shop ⇄ /shop/<slug> round-trips land where the user left off.
// • Hash nav (e.g. /#bundles) → smooth-scroll to the target.
// Belt-and-suspenders: HomePage also runs a route.hash watcher
// so that hash-only changes within the same route are caught
// even when Vue Router's scrollBehavior is short-circuited.
// • Everything else (forward route nav) → top of the page.
scrollBehavior(to, _from, savedPosition) {
// /shop ⇄ /shop/<slug> and / ⇄ /shop/<slug> round-trips land
// exactly where the user left off.
// • Same-route hash nav (e.g. clicking Bundles while on the
// home page) → smooth-scroll to the target.
// • Cross-route hash nav (e.g. /shop → /#bundles): the
// destination just mounted, so jump instantly.
// • Plain forward route nav → top of the page.
scrollBehavior(to, from, savedPosition) {
if (savedPosition) return savedPosition
if (to.hash) return { el: to.hash, behavior: 'smooth' }
if (to.hash) {
const sameRoute = from && from.path === to.path
return sameRoute
? { el: to.hash, behavior: 'smooth' }
: { el: to.hash }
}
return { top: 0 }
},
})