Canvas Frame
The one chrome every canvas screen sits in — account rail, work bar, scrolling surface, Inspector — and how the container screens and the document screen fill it differently.
Every screen under /app/canvas is drawn inside the same frame. Only what
goes in the middle changes.
In plain terms: one letterhead. The Workspace, a Project and a document are printed on it; the frame around them never moves.
One route, three screens
/app/canvas/$routeKey resolves the key to a folio and picks the screen from
its kind. /app/canvas itself provisions the user's Workspace and redirects
to it.
| Folio kind | Screen | Code |
|---|---|---|
| Workspace | Container list | src/pages/folio-container/ |
| Project | Container list | src/pages/folio-container/ |
| Document | Document Work Screen | src/pages/document-work/ |
Workspace and Project are one screen, not two: the same page, printing the tier's own words. The list screen shows the container's own card with its children filed beneath it; the document screen shows the document as modules and blocks. See Document Work Screen.
What the frame supplies
CanvasShell
├── Account rail ← collapsed by default, expands from the left edge
├── Work Bar ← the screen's own bar, passed in
├── Surface ← the scrolling middle; the screen itself
└── Inspector ← docked right-hand panelCanvasShell (src/widgets/canvas-shell/ui/canvas-shell.tsx) owns the two
nested sidebar providers and their widths. It takes the work bar, the surface
and the Inspector as slots and reads none of them — a screen supplies its own
words, never a tier flag.
Clearing the selection belongs to the frame, not the screen. Escape
anywhere inside the shell, or a click on empty surface, calls
onClearSelection. That is why each page owns its selection state and hands
the clearing down: the thing that clears it is the chrome around it.
Every screen goes through WorkScreen (GB-325): one chrome holding the
work bar (trail, Builder / Maker, the "…" menu) and the side panel with its
96px heading and Goldie. A screen supplies only its content.
The page header
Every page's frame carries one header (owner, 2026-10-01, second revision, fourth form): at the lid's right a labelled Share button opening one dialog with tabs Share | Library | Download (a Document has all three; Workspace, Project and Library Share alone; a Module or Block page has no Share). Beside it a muted readout: the seat holders' avatars · "Published in N Libraries", each opening its tab. The foot reads "Last edited by … · date ▾", opening the history. Insert stays on the list toolbar. See One Page Header for Every Page.
Inspector Panel rows
The panel is mounted on every canvas screen. Row names are stable; row content follows the screen and the selection.
| Row | Role |
|---|---|
| Selection Display Row | What the panel is currently acting on |
| Inspector Content Row | Assistance for that selection, capability-filtered |
| Conversation Panel | Transcript, tool-call cards, results, and the composer |
Where Goldie sits is the real difference between the screens:
- Document Work Screen — the Inspector carries the document-scoped
conversation. Arriving with a posture (
?surface=) gives the whole panel to Goldie, headedGoldie - Ask; without one it keeps itsInspectorheading and shows the selection rows above the conversation. - Container screens — the Inspector is present but empty ("Open a document to start a conversation"). The conversation happens in the open row's own Control Panel, one row at a time.
Readers hold no use-agent capability and get no conversation panel at all.
Narrow windows
Below the sidebar breakpoint (768px) the surface stays put and the Inspector
becomes a drawer: on the document screen Goldie is a bottom sheet with a
persistent minimized input dock; on a container screen the work bar's
right-hand trigger opens the panel. The work bar's left slot becomes the
account avatar, opening the account sidebar as a left drawer.
Runtime UI state
Goldie's posture, the outline state and the current selection are runtime UI state. They never create a document version, and a chat turn never clears the selection on its own.
The selection is supplied to the agent as ambient per-turn context — weak context, not an instruction. The agent uses it when the message refers to the selected item ("fill this", "change this clause") or when it materially grounds the answer. A stale or missing selection is refused server-side rather than acted on.
Related
- Document Work Screen
- Container Screen — the Workspace and Project listing
- Permissions and Visibility — roles, capabilities and the agent turn policy
- The Stack — the card furniture inside the surface
- Folios schema — what a routeKey resolves to