diff --git a/src/blobbi/companion/hooks/useRouteReaction.ts b/src/blobbi/companion/hooks/useRouteReaction.ts index d693bce7..ae7dfc7b 100644 --- a/src/blobbi/companion/hooks/useRouteReaction.ts +++ b/src/blobbi/companion/hooks/useRouteReaction.ts @@ -161,14 +161,32 @@ export function useRouteReaction({ const prevPathnameRef = useRef(pathname); const timeoutsRef = useRef[]>([]); - /** Last pointerdown position + timestamp. Updated on every pointerdown so - * the route-change effect can check whether there was a recent click. */ - const lastClickRef = useRef<{ position: Position; time: number } | null>(null); + /** Last pointerdown target + raw coordinates + timestamp. + * We store the nearest clickable element so we can re-read its live + * bounding rect at route-change time (accounts for scroll shifts + * between click and React effect). Raw coordinates serve as fallback + * if the element is unmounted by the time the effect runs. */ + const lastClickRef = useRef<{ element: Element | null; fallback: Position; time: number } | null>(null); - // Track pointer-down position (passive, no re-renders) + // Track pointer-down position + element (passive, no re-renders) useEffect(() => { const handler = (e: PointerEvent) => { - lastClickRef.current = { position: { x: e.clientX, y: e.clientY }, time: Date.now() }; + // Walk up from the event target to find the nearest or