Layout's controls move to the editor panel too
Colours, Typefaces and Padding sat below the preview and took their height from it — the same trade the
page builder's editors made, and undone for the same reason: this screen exists to be looked at, and
the controls were eating the thing being judged.
Announced through the same slot, so the panel still holds nothing and still knows nothing about what a
layout is.
One thing that does not survive the move: a JSX comment cannot be an argument. The block carried its
own `{/* … */}` above the tabs and it had to become an ordinary comment on the effect, which is where
the reasoning belongs anyway now that the element is announced rather than rendered in place.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -8,6 +8,7 @@ import { useSaveTarget } from '../SaveTarget';
|
||||
import { usePreviewable, useViewMode } from '../ViewMode';
|
||||
import { applyGutter, paintMeasure } from '../canvas';
|
||||
import { SitePreview, useDevPort } from '../SitePreview';
|
||||
import { useEditorSlot } from '../useEditorSlot';
|
||||
import { type LayoutBand } from './PaddingTab';
|
||||
import { GutterTab, type Gutter } from './GutterTab';
|
||||
|
||||
@@ -252,45 +253,28 @@ export const LayoutPanel = () => {
|
||||
[gutter],
|
||||
);
|
||||
|
||||
if (!draft) return <div className="p-4 text-xs text-muted-foreground">{error ?? 'Loading…'}</div>;
|
||||
const [, setEditor] = useEditorSlot();
|
||||
const setEditorRef = useRef(setEditor);
|
||||
setEditorRef.current = setEditor;
|
||||
|
||||
/*
|
||||
ONE layout for both modes: the preview takes the room, the controls take what they need.
|
||||
The layout's controls, handed to the editor panel.
|
||||
|
||||
It used to be two — View returned the preview alone, and Edit put a fixed 420px band above a
|
||||
scrolling column. That made the preview a letterbox in the mode where you are actually changing
|
||||
things, with empty panel below the controls, and it meant switching modes was a different component
|
||||
rather than a smaller one.
|
||||
They were below the preview and took their height from it — the same trade the page builder's
|
||||
editors made, and the same reason for undoing it: this screen exists to be looked at, and the
|
||||
controls were eating the thing being judged.
|
||||
|
||||
Now the column fills the panel and never scrolls as a whole. The preview is `flex-1`, so it is
|
||||
always as tall as whatever is left; the controls are `shrink-0`, so they are exactly as tall as
|
||||
their content and no taller. Edit takes height from the preview, and only as much as it needs.
|
||||
Announced rather than rendered, because the panel is a SIBLING — see useEditorSlot. The dependency
|
||||
list is everything the tabs DISPLAY; an element captures the props it was built with, so one left
|
||||
out here reads as a control that has stopped responding rather than as an error.
|
||||
*/
|
||||
return (
|
||||
<div className="flex size-full flex-col gap-3 p-4">
|
||||
{saved && <p className="shrink-0 text-xs text-success">Saved</p>}
|
||||
{error && <p className="shrink-0 text-xs text-destructive">{error}</p>}
|
||||
useEffect(() => {
|
||||
if (!draft) {
|
||||
setEditorRef.current(null);
|
||||
return;
|
||||
}
|
||||
|
||||
{/*
|
||||
The REAL page, embedded — not a drawing of it.
|
||||
|
||||
It was a React sketch: a centred row of labels, a body, a band at the bottom. It looked
|
||||
plausible and it was wrong, because the site's header has a logo hanging past a rule and a nav
|
||||
that sits in the content column. Worse, it was a second implementation of the layout, so it
|
||||
would have gone on being wrong differently every time either side changed.
|
||||
*/}
|
||||
<SitePreview port={devPort} path="layout" theme={themeProperties(draft)} onDocument={onDocument} />
|
||||
|
||||
{/*
|
||||
The controls as TABS, and only in Edit.
|
||||
|
||||
They were two stacked cards, which took as much height as both of them together — and every
|
||||
pixel of it came off the preview, which is the thing being judged. One at a time costs a click
|
||||
and gives the page back most of the panel.
|
||||
|
||||
`shrink-0` so they never take height from the preview, and no `max-h` any more: one tab is short
|
||||
enough that it does not need capping, which is the other thing this bought.
|
||||
*/}
|
||||
setEditorRef.current(
|
||||
<Tabs value={tab} onValueChange={setTab} className="shrink-0 gap-2">
|
||||
<TabsList className="h-7">
|
||||
<TabsTrigger value="colours" className="text-xs">
|
||||
@@ -322,7 +306,7 @@ export const LayoutPanel = () => {
|
||||
className={`col-start-1 row-start-1 ${tab === 'colours' ? '' : 'invisible'}`}
|
||||
aria-hidden={tab !== 'colours'}
|
||||
>
|
||||
<>
|
||||
<>
|
||||
<div className="flex flex-wrap gap-4">
|
||||
{COLOURS.map(({ key, label, fallback }) => (
|
||||
<div key={key} className="flex items-center gap-2">
|
||||
@@ -358,7 +342,7 @@ export const LayoutPanel = () => {
|
||||
className={`col-start-1 row-start-1 ${tab === 'typefaces' ? '' : 'invisible'}`}
|
||||
aria-hidden={tab !== 'typefaces'}
|
||||
>
|
||||
<>
|
||||
<>
|
||||
{/*
|
||||
Four across, one row.
|
||||
|
||||
@@ -423,7 +407,40 @@ export const LayoutPanel = () => {
|
||||
</div>
|
||||
</div>
|
||||
</Tabs>
|
||||
);
|
||||
}, [draft, tab, device]);
|
||||
|
||||
// Cleared on unmount, or the panel goes on offering Layout's controls over somebody else's page.
|
||||
useEffect(() => () => setEditorRef.current(null), []);
|
||||
|
||||
if (!draft) return <div className="p-4 text-xs text-muted-foreground">{error ?? 'Loading…'}</div>;
|
||||
|
||||
/*
|
||||
ONE layout for both modes: the preview takes the room, the controls take what they need.
|
||||
|
||||
It used to be two — View returned the preview alone, and Edit put a fixed 420px band above a
|
||||
scrolling column. That made the preview a letterbox in the mode where you are actually changing
|
||||
things, with empty panel below the controls, and it meant switching modes was a different component
|
||||
rather than a smaller one.
|
||||
|
||||
Now the column fills the panel and never scrolls as a whole. The preview is `flex-1`, so it is
|
||||
always as tall as whatever is left; the controls are `shrink-0`, so they are exactly as tall as
|
||||
their content and no taller. Edit takes height from the preview, and only as much as it needs.
|
||||
*/
|
||||
return (
|
||||
<div className="flex size-full flex-col gap-3 p-4">
|
||||
{saved && <p className="shrink-0 text-xs text-success">Saved</p>}
|
||||
{error && <p className="shrink-0 text-xs text-destructive">{error}</p>}
|
||||
|
||||
{/*
|
||||
The REAL page, embedded — not a drawing of it.
|
||||
|
||||
It was a React sketch: a centred row of labels, a body, a band at the bottom. It looked
|
||||
plausible and it was wrong, because the site's header has a logo hanging past a rule and a nav
|
||||
that sits in the content column. Worse, it was a second implementation of the layout, so it
|
||||
would have gone on being wrong differently every time either side changed.
|
||||
*/}
|
||||
<SitePreview port={devPort} path="layout" theme={themeProperties(draft)} onDocument={onDocument} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user