Fix thread scrubber anchoring

This commit is contained in:
dtonon 2026-08-27 22:50:03 +01:00
parent 7b80afbd6c
commit 997184cd66
2 changed files with 19 additions and 5 deletions

View file

@ -64,10 +64,11 @@
// The main column is its own scroll container (overflow-y-auto) and persists // The main column is its own scroll container (overflow-y-auto) and persists
// across navigations, so SvelteKit's window-only scroll restoration never // across navigations, so SvelteKit's window-only scroll restoration never
// resets it. Scroll it back to top on forward navigation; leave back/forward // resets it. Scroll it back to top on forward navigation; leave back/forward
// (popstate) alone so returning to a listing keeps its place. // (popstate) alone so returning to a listing keeps its place, and hash
// targets (#post-…) alone so the page can place the anchored post itself.
let mainEl = $state<HTMLElement | null>(null); let mainEl = $state<HTMLElement | null>(null);
afterNavigate((nav) => { afterNavigate((nav) => {
if (nav.type !== "popstate") mainEl?.scrollTo(0, 0); if (nav.type !== "popstate" && !nav.to?.url.hash) mainEl?.scrollTo(0, 0);
}); });
// Nothing is fetched until the relay confirms it will serve this visitor: // Nothing is fetched until the relay confirms it will serve this visitor:

View file

@ -390,12 +390,25 @@
await quotePost(post, text); await quotePost(post, text);
} }
// The scrubber sticks where the OP starts. Measure independently of the
// current scroll (the page may mount already scrolled, e.g. arriving from a
// profile with a reply link) and again when the header changes height.
$effect(() => { $effect(() => {
if (!opEl) return; const el = opEl;
const header = threadEl?.querySelector("[data-thread-header]");
if (!el || !header) return;
const main = document.querySelector("main"); const main = document.querySelector("main");
if (!main) return; if (!main) return;
opTopOffset = const measure = () => {
opEl.getBoundingClientRect().top - main.getBoundingClientRect().top; opTopOffset =
el.getBoundingClientRect().top -
main.getBoundingClientRect().top +
main.scrollTop;
};
measure();
const ro = new ResizeObserver(measure);
ro.observe(header);
return () => ro.disconnect();
}); });
</script> </script>