Workspace shell
A bar across the top, a rail down the left, and a main region that either fills the viewport or scrolls a column inside it — the frame for an operator tool, not a document.
What it is made of
GdWorkspaceShell— the frame: the viewport-height grid, the landmarks, the skip linkGdNavbarin#bar— spans the rail as well, because it names the APPLICATION rather than the current sectionGdNavRailin#rail— icon destinations- Optionally
#panel— a second column between rail and main (a layer list, a filter aside) - The page itself in the default slot
Three shells now exist and they do not overlap. GdAppShell is one centred column that scrolls the page — a document of CONTROLS. GdDocsShell is a reading column with a contents rail — a document of PROSE. This one is an APPLICATION: persistent chrome the content never scrolls past, and a canvas that may be a map.
Two main modes, and it is not a style choice
main="fill" gives main exactly the space left over and hides its overflow, so the content owns its own scrolling. That is what a map needs: a canvas sized by a parent that scrolls is a canvas resized on every scroll frame. main="column" makes main the scroll container and lands the content on the document column.
An app switches between them per route — the operator console's national map fills, its council pages scroll — under one persistent frame. That is why it is a prop on one component rather than two components: two would remount the chrome on every navigation between them.
column — main is the scroll container, so the bar and rail stay put with no position: sticky anywhere and no scroll-linked repaint of the chrome.
column — main is the scroll container, so the bar and rail stay put with no position: sticky anywhere and no scroll-linked repaint of the chrome.
column — main is the scroll container, so the bar and rail stay put with no position: sticky anywhere and no scroll-linked repaint of the chrome.
Routed destinations want links
GdNavRail is a tablist: it switches a panel, takes the WAI-ARIA tabs contract, and is driven by v-model. The specimen above uses it that way. An app whose rail navigates must not — a tab that changes the URL is a link wearing the wrong hat, and it loses middle-click and open-in-new-tab doing it. Compose GdNavRailItems inside your own anchors in the default slot and mark the active one yourself.
The rail is a slot on this shell rather than a prop for exactly that reason: taking items here would force one of those two shapes on every consumer, and the wrong one is a real accessibility regression.