diff --git a/web/WorkPanel.tsx b/web/WorkPanel.tsx
new file mode 100644
index 0000000..fd9a9c5
--- /dev/null
+++ b/web/WorkPanel.tsx
@@ -0,0 +1,53 @@
+import type { LayoutNode } from 'officerdev';
+import { WorkspaceView } from 'officerdev';
+import { useAuthoredLayout } from 'state/useAuthoredLayout';
+
+/**
+ * The preview and its editor, as a workspace inside one panel.
+ *
+ * ── Why not two more panels in the root layout ──
+ *
+ * They were, and nesting them as a GROUP looked identical: a horizontal group inside a horizontal group
+ * renders three columns, because that is what it is. All the nesting bought was which divider moved
+ * what, which is invisible until you drag one.
+ *
+ * A workspace inside a panel is a real container. The pair sits in one panel with its own chrome, its
+ * own dividers and its own persisted sizes, and the outer layout has two children rather than three —
+ * so the shape on screen is the shape in the file.
+ *
+ * ── Its structure is the author's; only the sizes are yours ──
+ *
+ * `useAuthoredLayout`, not `useDashboardState`. The latter persists the whole tree, which is right for
+ * a dashboard somebody arranged and wrong here: the structure would freeze at whatever it was the first
+ * time this screen was opened, and a change shipped later would never reach anybody who had already
+ * looked. Sizes and zoom persist; the shape comes from this file every render.
+ *
+ * ── Its own key ──
+ *
+ * `screens/plugin/fofos-admin/work`, beside the root's `screens/plugin/fofos-admin`. Two layouts, two
+ * keys: sharing one would have the inner and outer trees persisting over each other's sizes.
+ */
+const workLayout: LayoutNode = {
+ type: 'group',
+ id: 'fofos-admin-work',
+ direction: 'horizontal',
+ children: [
+ { node: { type: 'panel', id: 'fofos-admin-detail', appType: 'fofos-admin-detail' }, size: 70 },
+ { node: { type: 'panel', id: 'fofos-admin-editor', appType: 'fofos-admin-editor' }, size: 30 },
+ ],
+};
+
+const ALLOWED = ['fofos-admin-detail', 'fofos-admin-editor'];
+
+export const WorkPanel = () => {
+ const workspace = useAuthoredLayout('screens/plugin/fofos-admin/work', workLayout);
+
+ return (
+
+ {/* `locked`, like the screen around it: this arrangement is the plugin author's design, not a
+ workspace to rearrange. `allowed` pins it to these two, so a persisted layout naming anything
+ else falls back rather than rendering some other plugin's panel in here. */}
+
+
+ );
+};
diff --git a/web/layout.ts b/web/layout.ts
index 2cbddd9..b27b863 100644
--- a/web/layout.ts
+++ b/web/layout.ts
@@ -3,16 +3,15 @@ import type { LayoutNode } from 'officerdev';
/**
* A nav down the left, and beside it the pair that does the work.
*
- * ── Why the preview and the editor are a GROUP ──
+ * ── Two children, not three ──
*
- * They were three siblings — nav, preview, editor — and the nesting is the whole difference. With three
- * in a row every divider is between two of them, so widening the editor took from the preview and
- * dragging the nav re-proportioned all three: three panels that can only be sized against each other.
+ * The preview and its editor are a WORKSPACE INSIDE A PANEL — see WorkPanel — rather than two more
+ * children here. Nesting them as a group was tried first and looked identical: a horizontal group in a
+ * horizontal group renders three columns, because that is what it is, and all the nesting bought was
+ * which divider moved what.
*
- * Nested, the outer divider moves the nav against THE WORK, and the inner one splits the work between
- * looking and changing. Those are the two questions somebody actually has — "give me more room to
- * work" and "I need more of the controls right now" — and each is now one drag that leaves the other
- * answer alone.
+ * A panel is a real container. The pair has its own chrome, its own dividers and its own persisted
+ * sizes, and this file has two children — so the shape on screen is the shape in the file.
*
* ── The nav is the narrow one ──
*
@@ -35,17 +34,6 @@ export const defaultLayout: LayoutNode = {
direction: 'horizontal',
children: [
{ node: { type: 'panel', id: 'fofos-admin-nav', appType: 'fofos-admin-nav' }, size: 22 },
- {
- node: {
- type: 'group',
- id: 'fofos-admin-work',
- direction: 'horizontal',
- children: [
- { node: { type: 'panel', id: 'fofos-admin-detail', appType: 'fofos-admin-detail' }, size: 70 },
- { node: { type: 'panel', id: 'fofos-admin-editor', appType: 'fofos-admin-editor' }, size: 30 },
- ],
- },
- size: 78,
- },
+ { node: { type: 'panel', id: 'fofos-admin-work', appType: 'fofos-admin-work' }, size: 78 },
],
};
diff --git a/web/panels.ts b/web/panels.ts
index f3f8ba4..399be8e 100644
--- a/web/panels.ts
+++ b/web/panels.ts
@@ -1,9 +1,10 @@
import type { AppRegistryMeta } from 'officerdev';
-import { List, PanelRight, SlidersHorizontal } from 'lucide-react';
+import { Columns2, List, PanelRight, SlidersHorizontal } from 'lucide-react';
import { NavPanel } from './NavPanel';
import { DetailPanel } from './DetailPanel';
import { DetailHeader } from './DetailHeader';
import { EditorPanel } from './EditorPanel';
+import { WorkPanel } from './WorkPanel';
/**
* Three panels: a nav, whatever it selects, and where an editor opens.
@@ -33,6 +34,20 @@ export const appRegistryMetas: AppRegistryMeta[] = [
header: DetailHeader,
availableOnPanel: false,
},
+ {
+ /*
+ The container the root layout points at: a workspace holding the preview and its editor.
+
+ Registered like any other panel because the outer WorkspaceView resolves by appType, and listed in
+ the root's allow-list. The two it contains stay registered too — the INNER workspace resolves them
+ the same way.
+ */
+ key: 'fofos-admin-work',
+ name: 'Work',
+ icon: Columns2,
+ component: WorkPanel,
+ availableOnPanel: false,
+ },
{
key: 'fofos-admin-editor',
name: 'Editor',