the open page lists its bands in the nav
A third level, under the selected page only — every page has bands, and listing all of them would make the nav longer than the site. Announced by the builder rather than fetched again: it already reads them to know what it is looking at in the document, and it mounts exactly when a page is open. Cleared on unmount, or the nav keeps listing the last page's bands. Clicking one writes a third URL segment and the preview scrolls to it, keyed on the render count too so the position survives a save replacing the frame. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -35,7 +35,7 @@ import { useEditorSlot } from '../useEditorSlot';
|
||||
import { AddComponentDialog, type ComponentKind } from './AddComponentDialog';
|
||||
import { MediaPicker } from '../MediaPicker';
|
||||
import { GalleryPicker } from '../GalleryPicker';
|
||||
import { pageFromParam, usePages, type Page } from '../usePages';
|
||||
import { pageFromParam, usePages, useSections, type Page } from '../usePages';
|
||||
|
||||
/**
|
||||
* One page, being built.
|
||||
@@ -57,10 +57,14 @@ export const PageBuilderPanel = () => {
|
||||
const clientRef = useRef(client);
|
||||
clientRef.current = client;
|
||||
|
||||
const { item: slug } = useNav();
|
||||
const { item: slug, part } = useNav();
|
||||
|
||||
const devPort = useDevPort();
|
||||
const { pages, announce } = usePages();
|
||||
const { announceSections } = useSections();
|
||||
// Cleared when this unmounts, or the nav goes on listing the last page's bands under whatever is
|
||||
// selected next.
|
||||
useEffect(() => () => announceSections(null), [announceSections]);
|
||||
|
||||
// This section has a preview, so the bar offers Edit/View and the three widths — the same opt-in
|
||||
// Layout makes. Pages, the list, does not: there is nothing there to view at tablet width.
|
||||
@@ -160,6 +164,21 @@ export const PageBuilderPanel = () => {
|
||||
*/
|
||||
const frameDoc = useRef<Document | null>(null);
|
||||
|
||||
/*
|
||||
The band named by the third URL segment, brought into view.
|
||||
|
||||
That segment is what the nav's rows under the open page write, and this is what makes them do
|
||||
something. `rendered` is a dependency as well as `part`: the frame is replaced on every write, and
|
||||
a scroll issued against the old document would be lost — this way the position survives a save.
|
||||
|
||||
The band is found by `data-section-id`, the marker the site already carries for the admin.
|
||||
*/
|
||||
useEffect(() => {
|
||||
if (!part) return;
|
||||
const band = frameDoc.current?.querySelector(`[data-section-id="${CSS.escape(part)}"]`);
|
||||
band?.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||
}, [part, rendered]);
|
||||
|
||||
const onDocument = useCallback(
|
||||
(frameDocument: Document) => {
|
||||
frameDoc.current = frameDocument;
|
||||
@@ -246,6 +265,9 @@ export const PageBuilderPanel = () => {
|
||||
.get<{ data: CanvasSection[]; steps?: number[] }>(`/fofos-admin/pages/${page.id}/sections`)
|
||||
.then((response) => {
|
||||
setSections(response.data);
|
||||
// The nav draws these as rows under the open page — see useSections for why it is announced
|
||||
// rather than fetched a second time.
|
||||
announceSections(response.data.map((section) => ({ id: section.id, name: section.name })));
|
||||
if (response.steps) setSteps(response.steps);
|
||||
})
|
||||
.catch((failure: unknown) => setError(readableError(failure)));
|
||||
|
||||
Reference in New Issue
Block a user