a reload lands where you were, not at the top

The scroll ran on `rendered` changing, which is the moment the reload STARTS —
frameDoc still pointed at the outgoing document, so it scrolled the page about to
be replaced and the new one arrived at the top. Every write from the editor did
it: reorder a gallery or a partner, lose your place.

It now happens in onDocument, against the document that has just loaded. The
effect stays for the other case — a different band chosen with no reload — and
keeps its smooth scroll, because there you are watching it move.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-01 20:58:23 +01:00
co-authored by Claude Opus 5
parent 4435537ae2
commit 2ec48a1a76
+25 -1
View File
@@ -219,11 +219,23 @@ export const PageBuilderPanel = () => {
The band is found by `data-section-id`, the marker the site already carries for the admin.
*/
/*
Read inside `onDocument`, which runs against the document that has just LOADED.
The effect below cannot do that job: bumping `rendered` runs it immediately, while `frameDoc` still
points at the outgoing document — so it scrolled the page that was about to be replaced, and the
new one arrived at the top. Every write from the editor did that: reorder a gallery, lose your
place.
*/
const partRef = useRef<string | null>(part);
partRef.current = part;
useEffect(() => {
// A different band chosen, with no reload. `smooth`, because you are watching it move.
if (!part) return;
const band = frameDoc.current?.querySelector(`[data-section-id="${CSS.escape(part)}"]`);
band?.scrollIntoView({ behavior: 'smooth', block: 'start' });
}, [part, rendered]);
}, [part]);
const onDocument = useCallback(
(frameDocument: Document) => {
@@ -236,6 +248,18 @@ export const PageBuilderPanel = () => {
the screen where things are placed. It also answers the question a negative margin asks: a
block escaping the gutter has to be seen escaping it, against the line it crossed.
*/
/*
Back to where you were, in the document that just arrived.
`auto` and not `smooth`: this is a fresh document and there is nothing to watch move — a smooth
scroll from the top would animate past everything above the band for no reason.
*/
if (partRef.current) {
frameDocument
.querySelector(`[data-section-id="${CSS.escape(partRef.current)}"]`)
?.scrollIntoView({ behavior: 'auto', block: 'start' });
}
const measure = paintMeasure(frameDocument);
const selection = paintSelection(frameDocument, {
sections,