diff --git a/web/sections/PageBuilderPanel.tsx b/web/sections/PageBuilderPanel.tsx index aada984..595e848 100644 --- a/web/sections/PageBuilderPanel.tsx +++ b/web/sections/PageBuilderPanel.tsx @@ -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(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,