fix: jump to top on page change before post deep-link alignment
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 26s
All checks were successful
Deploy to Frontend Servers / deploy (push) Successful in 26s
Entering /browse via a popular-section card carried ?post=, which made ScrollToTop skip the reset entirely. The window stayed at the previous page's bottom scroll, so the deep-link animation visibly scrolled UP from the bottom to the target post. Now any pathname change jumps to the top first (even with ?post=), letting the destination align to the post by scrolling down from the top. Hash anchors and same-page ?post= changes are still left alone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,21 +1,45 @@
|
||||
import { useEffect } from "react";
|
||||
import { useEffect, useRef } from "react";
|
||||
import { useLocation } from "react-router-dom";
|
||||
|
||||
/**
|
||||
* Resets the window to the top on every route change. React Router does not
|
||||
* restore scroll on client navigation, so without this a short new page would
|
||||
* clamp to wherever the previous (taller) page was scrolled — e.g. landing at
|
||||
* the bottom of a category page after clicking a card far down the home grid.
|
||||
* Resets the window to the top on client navigation. React Router does not
|
||||
* restore scroll on its own, so without this a short new page would clamp to
|
||||
* wherever the previous (taller) page was scrolled — e.g. landing at the bottom
|
||||
* of a category page after clicking a card far down the home grid.
|
||||
*
|
||||
* Skips navigations that carry a hash (`#post-<id>`, `#categories`, …) or a
|
||||
* `?post=<id>` deep link so the target page can handle its own alignment.
|
||||
* Navigating to a *different* page always jumps to the top, even when the URL
|
||||
* carries `?post=<id>`. The destination's own deep-link logic then aligns to
|
||||
* that post by scrolling DOWN from the top, instead of animating UP from the
|
||||
* previous page's bottom scroll — which looked like the page "scrolling up from
|
||||
* the bottom" after tapping a popular-section card.
|
||||
*
|
||||
* A hash (`#post-<id>`, `#categories`, …) is left alone so the target page can
|
||||
* handle its own anchor alignment. A same-page `?post=` change (clicking
|
||||
* another card while already on the list) is also left alone so it doesn't
|
||||
* fight the in-page alignment.
|
||||
*/
|
||||
export function ScrollToTop() {
|
||||
const { pathname, search, hash } = useLocation();
|
||||
const prevPathname = useRef(pathname);
|
||||
|
||||
useEffect(() => {
|
||||
if (hash || new URLSearchParams(search).has("post")) return;
|
||||
window.scrollTo({ top: 0, left: 0 });
|
||||
const pathnameChanged = prevPathname.current !== pathname;
|
||||
prevPathname.current = pathname;
|
||||
|
||||
if (hash) return;
|
||||
|
||||
// Entering a new page: always start at the top (post deep-links align
|
||||
// afterwards from here).
|
||||
if (pathnameChanged) {
|
||||
window.scrollTo({ top: 0, left: 0 });
|
||||
return;
|
||||
}
|
||||
|
||||
// Same page, search-only change (e.g. switching sort/filter): reset to top
|
||||
// unless it's an in-page post deep-link, which handles its own alignment.
|
||||
if (!new URLSearchParams(search).has("post")) {
|
||||
window.scrollTo({ top: 0, left: 0 });
|
||||
}
|
||||
}, [pathname, search, hash]);
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user