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',