Files
fofos-admin/web/EditorPanel.tsx
T
pastilhasandClaude Opus 5 1ec361d006 a block's spacing sits with its title; page settings need the page selected
Spacing had a link in the chrome painted onto the page and lost its door with the
rest of it. It belongs beside the heading: both are properties of the selected
block, and one of the two is not worth a place of its own to go to.

The page's name and address now show only when the page row itself is selected.
With a band or a block open they sat above an editor about something else and
read as belonging to it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-01 19:50:18 +01:00

89 lines
4.0 KiB
TypeScript

import { DeviceToggle } from './DeviceToggle';
import { PageSettings } from './sections/PageSettings';
import { useNav } from './routes';
import { pageFromParam, usePages } from './usePages';
import { useEditorSlot } from './useEditorSlot';
/**
* Where an editor opens — a column beside the preview rather than a drawer beneath it.
*
* It was rendered under the frame, which took the height from the thing being edited: choosing a
* spacing shrank the page you were choosing it for, and on a laptop the preview lost a third of itself
* to a row of two dropdowns. A panel keeps the page whole and puts the controls where a workspace puts
* controls.
*
* It holds nothing of its own except the width. The panel that owns a selection builds the editor and
* announces it — see useEditorSlot for why it carries the element rather than a description of one.
*
* ── The device toggle is here, above everything ──
*
* It was in a bar across the top of the detail panel, which put it beside Sync and Publish — three
* things that act on the SITE next to one that decides how you are looking at it. It belongs with the
* settings it scopes: a spacing is chosen per width, and the control saying which width should be the
* first thing in the column those choices are made in.
*
* Always drawn, including when nothing is selected. It is not part of the editor — it decides what the
* PREVIEW shows, so hiding it until a block is picked would mean selecting something to change the
* width and then deselecting it.
*
* It reads `?device=` rather than a context, which is what lets it live in a panel that is a sibling of
* the one holding the preview. See DeviceToggle.
*/
export const EditorPanel = () => {
const [editor] = useEditorSlot();
/*
The selected page's own settings, above everything.
Read here rather than announced like the editor below it, because they are not the editor: they
belong to the page whatever is selected inside it, and a block being picked must not replace them.
Above the device toggle, because the toggle scopes what is under it to one width and none of these
three have widths.
*/
const { section, item, part } = useNav();
const { pages } = usePages();
/*
Only when the PAGE row itself is selected.
A band or a block selected means the editor below is about that, and the page's own name and
address sitting above it read as belonging to whatever is open. They are reached by pressing the
page again, which is what the nav already implies.
*/
const page = section === 'pages' && !part ? pageFromParam(pages, item) : null;
return (
<div className="flex size-full flex-col overflow-hidden">
{page && (
<div className="shrink-0 border-b border-border px-3 py-3">
<PageSettings page={page} />
</div>
)}
{/* Outside the scroll area, so a long editor cannot carry it off the screen. */}
<div className="shrink-0 border-b border-border px-3 py-2">
<DeviceToggle />
</div>
{editor ? (
/*
`@container`, once, for every section inside it.
The sections lay out in two columns and have to fall back to one when the panel is dragged
narrow — and the window's width says nothing about that, because the width here is a divider
somebody moves. Declared on the scroller rather than per section, so a new section is
responsive by being in the column rather than by remembering to say so.
*/
<div className="@container min-h-0 flex-1 overflow-auto p-3">{editor}</div>
) : (
<div className="flex min-h-0 flex-1 items-center justify-center p-6 text-center">
{/* Names what the panel is FOR rather than saying it is empty. "Nothing selected" describes
this component's state; this describes the reader's next move. */}
<p className="text-xs text-muted-foreground">
Pick a block in the page to edit it, or press Spacing on a band.
</p>
</div>
)}
</div>
);
};