fix(nav): hand scroll restoration back to the browser after arrival

This commit is contained in:
Evandro Fonseca Junior committed 2026-09-13 04:35:00 -03:00
1 parent 9aff4d1035
commit b181216a35
3 files changed
+45 -8

No files matched your search

@@ -16,6 +16,17 @@ function focusFragment(target: HTMLElement) {
target.focus({ preventScroll: true });
}
/**
* A document owns one outstanding homepage arrival. Later mounts are same-document
* history, where the browser restores its own position.
*/
let arrivalSettled = false;
/** Tests replay several documents inside one jsdom document. */
export function resetHomeArrivalState() {
arrivalSettled = false;
}
/** Correct only an outstanding arrival; ordinary links and history keep native scrolling. */
export function useHomeFragmentNavigation() {
const ready = useRef(false);
@@ -26,12 +37,11 @@ export function useHomeFragmentNavigation() {
| PerformanceNavigationTiming
| undefined;
// A history restoration owns its saved position, not the URL's old fragment.
let pending =
navigation?.type === "back_forward" ? "" : window.location.hash;
let pendingTop =
navigation?.type !== "back_forward" && !window.location.hash;
if (navigation?.type !== "back_forward")
window.history.scrollRestoration = "manual";
const restoration = navigation?.type === "back_forward";
const arrival = !restoration && !arrivalSettled;
let pending = restoration ? "" : window.location.hash;
let pendingTop = arrival && !window.location.hash;
if (arrival) window.history.scrollRestoration = "manual";
const resolve = () => {
if (!ready.current) return;
@@ -69,6 +79,7 @@ export function useHomeFragmentNavigation() {
const cancelArrival = () => {
pending = "";
pendingTop = false;
window.history.scrollRestoration = "auto";
};
const onKeyDown = (event: KeyboardEvent) => {
if (
@@ -151,5 +162,7 @@ export function useHomeFragmentNavigation() {
return useCallback(() => {
ready.current = true;
resolveArrival.current?.();
arrivalSettled = true;
window.history.scrollRestoration = "auto";
}, []);
}