When building web applications, the industry has well-established languages for two layers of design:
- Component design has atomic design — atoms, molecules, organisms — a structured vocabulary for building UI elements
- Visual design has design tokens, design systems, and tools like Figma
But there has been no equivalent formal language for the application shell — the structural architecture of how an application is laid out, how regions relate to each other, and how the layout changes in response to user interaction, content, and screen size.
The Shell Design Language (SDL) fills that gap. It gives designers, developers, and product teams a shared vocabulary to describe, discuss, and specify the structural layer of an application before a line of code is written — or to document an existing application's architecture precisely.
SDL operates at the layer above components and below visual design. It is framework-agnostic, tool-agnostic, and technology-agnostic.
SDL is built from four layers:
- Region Types — what structural elements exist
- Region Behaviours — how each region acts
- Anchor Zones — internal structure within regions
- Named Compositions — common patterns built from regions
Two cross-cutting concepts apply across all layers:
- Transitions — how the shell changes over time
- Panel Groups — how multiple simultaneous Panels coexist
Every structural element in an application shell is one of five region types.
The outermost container of the application. The Chrome is the root of the shell — it frames everything else and defines the absolute boundary of the application.
- Always occupies the full viewport (
100vh,100vw) - Never scrolls itself (
overflow: hidden) - Contains all other regions
- Typically implemented as a CSS Grid at the root level
The Chrome is not usually visible as a distinct element — it is the invisible container that makes independent scrolling in child regions possible. Without overflow: hidden on the Chrome, child regions cannot have their own independent scroll contexts.
A fixed-dimension region inside the Chrome. Anchors provide persistent navigation, toolbars, status bars, and utility controls.
Properties:
- Axis — horizontal (top/bottom) or vertical (left/right)
- Position — leading (left/top), trailing (right/bottom)
- Dimension — fixed size, collapsible (snaps between two sizes), or resizable (user-draggable)
- Persistence — always visible, or conditionally visible
- Span — full-span or inset (see Anchor Span below)
Examples: sidebar navigation, top header bar, bottom status bar, toolbar
A flexible region that fills remaining space after Anchors are placed. A Viewport owns its own scroll context — it scrolls independently of all other regions. An application shell can contain multiple Viewports simultaneously.
Properties:
- Scroll behaviour — vertical, horizontal, spatial (pan/zoom), or none
- Viewport Mode — how its content is navigated (see Layer 2)
The Viewport is where application content lives. Everything inside a Viewport — components, lists, forms, conversations — belongs to that Viewport's scroll context.
A region that is dynamically inserted into the layout in response to content or application state. Unlike an Anchor, a Panel is not structurally present in the layout at all times — it appears and disappears, changing the layout when it does.
Properties:
- Position — leading or trailing relative to the adjacent Viewport
- Dimension — fixed width/height, or resizable
- Trigger — what causes it to appear (see Triggers, below)
- Dismissal — how it closes (user action, state change, or both)
Critical distinction from Overlay: A Panel participates in the layout — it compresses adjacent Viewports when it appears. An Overlay floats above the layout and leaves it unchanged.
Examples: an artifact/preview panel that opens when editing code, a detail panel in a master-detail view, a properties panel in a design tool
A region that appears above the layout temporarily without affecting the layout of other regions beneath it.
Overlays come in two distinct subtypes:
Modal Overlay
- Positionally independent — centred relative to the Chrome regardless of where it was triggered
- Dims or blocks interaction with the rest of the shell
- Requires explicit dismissal before the user can continue
- Examples: confirmation dialogs, onboarding flows, settings screens
Anchored Overlay
- Positionally dependent — anchors itself to the element that triggered it
- Does not dim the shell; does not block interaction elsewhere
- Has a preferred direction (up, down, left, right) but detects available space and flips if needed
- Examples: dropdown menus, drop-up menus, tooltips, context menus, date pickers, command palettes
Note on Anchored Overlays and CSS: The CSS Anchor Positioning API, now landing in modern browsers, provides native browser support for the positioning logic Anchored Overlays require.
Each region has a set of behaviours that define how it acts at runtime.
A Viewport's mode describes how its content is navigated:
| Mode | Description | Examples |
|---|---|---|
| Linear | Content scrolls continuously in one direction. No switching between states. | A conversation thread, an article, a feed |
| Staged | Content swaps between discrete states, driven by a navigation control. | Tab bars, segmented controls, wizard steps |
| Routed | Content is driven by the URL. Typically involves a full region transition on navigation. | Standard page routing in most web applications |
| Spatial | Content exists in a two-dimensional coordinate space navigated by panning and zooming. The Viewport is a camera over a canvas, not a window over a flow. | Design tools (Figma, Miro), maps, node editors |
| Behaviour | Description |
|---|---|
| Fixed | The Anchor has a defined size that does not change |
| Collapsible | The Anchor snaps between two sizes — expanded and collapsed. In collapsed state it may show only icons, abbreviated labels, or nothing |
| Resizable | The user can drag the Anchor boundary to any size within defined min/max constraints |
How a region responds when the viewport narrows below a defined breakpoint. This is a mode change, not a CSS reflow — it often requires JavaScript state, not just CSS.
| Response | Description |
|---|---|
| Persist | Region remains visible and unchanged |
| Collapse | Region collapses to minimum dimension |
| Lift | Region detaches from the layout and becomes an Anchored Overlay (e.g. a sidebar becomes a drawer) |
| Disappear | Region is removed from the layout entirely |
What causes a Panel to appear:
| Trigger | Description | Example |
|---|---|---|
| User-initiated | Explicit user action — a button click, menu selection | Opening a settings panel |
| Content-initiated | The Panel appears because of the type or state of content in an adjacent Viewport | A code preview panel appearing when the user writes a code block |
| State-initiated | Application state causes the Panel to appear | A notification panel appearing when a background task completes |
Content-initiated triggers deserve special architectural attention: they create a dependency between a Viewport's content and the surrounding shell structure. The content is effectively reaching up and changing the layout around itself. This has significant implications for state management — the wiring between content state and shell structure must be explicitly designed.
A controller relationship exists when an Anchor contains a navigation control that drives the content of a Viewport. The Anchor and the Viewport it controls are linked — the state of the navigation control in the Anchor determines which content mode the Viewport is in.
This relationship must be explicitly identified during design and explicitly implemented in code. It is a common source of bugs when left implicit.
A controller relationship may also exist between two Anchors. This occurs when a control in one Anchor drives the state of a different Anchor — most commonly, a toggle button in the top Anchor that collapses or expands the leading Anchor (the sidebar toggle / hamburger pattern).
This is one of the most common patterns in web applications and is almost always left implicit in design documentation, which is precisely why it causes bugs. The wiring between the toggle button and the Anchor it controls must cross region boundaries in the application state, and without naming it, that crossing is often forgotten or implemented inconsistently.
An Anchor-to-Anchor controller relationship must specify:
- Which Anchor contains the control (the controller Anchor)
- Which Anchor is being controlled (the target Anchor)
- What state the control drives (typically: collapsed / expanded)
- Whether the control reflects current state visually (i.e. does the button icon change when the sidebar is collapsed?)
In an SDL description, write: Top Anchor contains sidebar toggle, Anchor-to-Anchor controller of Leading Anchor collapse state.
Anchor Span describes how an Anchor relates spatially to perpendicular Anchors — specifically, whether it runs the full dimension of the Chrome on its axis or whether it yields space to Anchors on the perpendicular axis.
| Span | Description | CSS Grid implication |
|---|---|---|
| Full-span | The Anchor runs the full width or height of the Chrome, regardless of what other Anchors are present on the perpendicular axis. | The full-span Anchor occupies an entire grid row or column at the Chrome level. Perpendicular Anchors start inside it. |
| Inset | The Anchor runs only the portion of its axis not occupied by full-span perpendicular Anchors. | The inset Anchor shares its grid row or column with the full-span Anchor's allocated space. |
Anchor Span is a property of the Chrome, not of the individual Anchor, because it describes a relationship between Anchors. Like Corner Ownership for Panel Groups, it must be specified before the root CSS Grid is defined — changing it later requires reworking the Chrome layout.
Span must be specified for every Anchor in the shell. When two Anchors are on perpendicular axes (e.g. a top Anchor and a leading Anchor), exactly one of them must be full-span and the other inset. When both claim full-span, the result is a conflict that must be resolved explicitly.
Common patterns:
| Pattern | Top Anchor | Leading Anchor | Example |
|---|---|---|---|
| Header-dominant | Full-span | Inset (starts below header) | Claude Desktop, most SaaS apps |
| Sidebar-dominant | Inset (fills remaining width) | Full-span (runs full height) | Classic email clients, some IDEs |
| Both inset | Neither full-span — they share the corner | — | Rare, requires explicit corner treatment |
Why it matters: A full-span top Anchor means the sidebar toggle button can live in the header and visually span the entire width of the application — the most common placement. An inset top Anchor means the header starts only at the right edge of the sidebar, and there is no natural place in the header for a sidebar toggle that spans the full width.
In most shells the controller relationship is one-directional: an Anchor drives a Viewport. In Canvas applications this relationship runs both ways. The Viewport's selection state drives what the surrounding Panels and Anchors display — selecting an object on the canvas changes the properties Panel, the layers Panel, and the active tool state simultaneously.
This is architecturally distinct from a standard controller relationship and must be named explicitly when present. It has significant state management implications: the Viewport is no longer a passive recipient of navigation commands but an active emitter of selection events that reshape the surrounding shell.
Bidirectional controller relationships should be specified as:
- Which Panels and Anchors are driven by Viewport selection state
- What selection states trigger which changes (single object selected, multiple selected, nothing selected)
- What the default state of those Panels is when nothing is selected
A Spatial Viewport has properties and behaviours that do not apply to other Viewport modes. When a Viewport is declared as Spatial, the following must also be specified:
Navigation model — how the user moves around the canvas:
| Navigation | Description |
|---|---|
| Pan | Translate the camera in X and Y. Typically two-finger drag, middle-click drag, or spacebar + drag. |
| Zoom | Scale the camera. Typically pinch gesture or scroll wheel. |
| Fit to screen | Reset the camera so all content is visible. Typically a keyboard shortcut. |
| Zoom to selection | Move the camera to frame the currently selected objects. |
| Reset | Return to origin at 100% zoom. |
Not all navigation modes need to be supported. Which ones are available must be specified.
Coordinate system — Spatial Viewports maintain two coordinate systems simultaneously:
- World coordinates — the position of objects in the canvas space, independent of zoom and pan
- Screen coordinates — the position of objects on the user's display, dependent on current camera state
This distinction is not merely technical. It affects how hit testing works, how snapping and alignment tools operate, and how the minimap represents position. The SDL does not specify implementation, but noting that a Spatial Viewport operates in world coordinates is important for communicating intent.
Object model — unlike Linear Viewports where content flows in document order, a Spatial Viewport contains positioned objects in a coordinate space. The SDL should note the object model type:
| Object Model | Description | Examples |
|---|---|---|
| Free-form | Objects may be placed anywhere in the coordinate space with no constraints | Whiteboards (Miro), illustration tools |
| Node graph | Objects are nodes connected by edges. Position is meaningful but constrained by connection topology | Node editors, flow builders, pipeline tools |
| Frame-based | Objects exist within named frames or artboards that provide organisational structure | Design tools (Figma), presentation tools |
| Tile-based | The coordinate space is divided into a discrete grid. Objects occupy cells | Maps, strategy games, grid editors |
Selection model — in a Spatial Viewport, selection is a shell-level concern, not a component-level concern. The selection model must be specified:
| Selection Type | Description |
|---|---|
| Single | One object may be selected at a time |
| Multi | Multiple objects may be selected simultaneously via shift-click or marquee |
| Hierarchical | Objects may be selected at different levels of nesting (e.g. a group, then a child within the group) |
The minimap is a region type unique to Spatial Viewports. It is a small thumbnail representation of the entire canvas that shows the current camera position and allows direct navigation by clicking or dragging within the thumbnail.
The minimap does not fit cleanly into existing SDL region types:
- It is not an Anchor — it has no fixed axis and does not compress the Viewport
- It is not an Overlay — it is persistent, not triggered
- It is not a Panel — it participates in the Viewport visually but not structurally
The minimap is therefore defined as a Viewport Fixture — a persistent, non-structural element that is positionally fixed within a Viewport (typically a corner) and serves both display and navigation purposes.
Minimap properties:
- Position — which corner of the Viewport it occupies (typically bottom-right)
- Default visibility — visible or hidden until triggered
- Toggle — whether the user can show/hide it
- Navigation — whether clicking/dragging the minimap moves the camera (most do)
Anchors are not flat — they have internal structure. Most real Anchors have distinct zones with different layout rules and persistence behaviour.
| Zone | Description | Typical Contents |
|---|---|---|
| Anchor Header | The top portion of an Anchor. Fixed position within the Anchor. | Workspace/org switcher, app logo, search bar |
| Anchor Body | The middle portion of an Anchor. This zone may itself scroll independently if its content exceeds available space. | Navigation items, conversation list, file tree |
| Anchor Footer | The bottom portion of an Anchor. Fixed position within the Anchor, always visible regardless of Anchor Body scroll position. | User profile, account controls, utility actions |
The Anchor Footer is a particularly important pattern: it provides persistent utility controls that must always be accessible, regardless of how far the user has scrolled through the Anchor Body.
Elements in the Anchor Footer typically trigger Overlays — either Anchored Overlays (for quick access menus like a user profile drop-up) or Modal Overlays (for heavier flows like inviting team members).
Named compositions are common shell patterns built from the region types above. Naming them allows teams to communicate the overall structure of an application in a single term.
Structure: One leading Anchor (sidebar) + one Viewport
The dominant pattern for productivity applications and tools. The sidebar provides navigation or context; the Viewport shows content.
Typical breakpoint response for the Anchor: Collapse or Lift
Examples: Claude, VS Code, Slack, Notion, Gmail
Variant — Workspace with Controller: When the Viewport operates in Staged mode, driven by a tab bar in the top Anchor, this is a Workspace with a Controller relationship between the header Anchor and the main Viewport.
Structure: Two Viewports side by side, where selection in the left Viewport drives content in the right Viewport
The left Viewport acts as a navigable list; the right Viewport shows the detail of whatever is selected. A controller relationship exists between the two Viewports.
Typical breakpoint response: At narrow widths, the left Viewport becomes an Anchor or disappears, and the right Viewport fills the Chrome.
Examples: Email clients, file browsers, settings screens with category lists
Structure: One Spatial Viewport surrounded by Anchors and Panel Groups containing tools, properties, and organisational controls
The Canvas composition is the most structurally complex of the named compositions because it involves a Bidirectional Controller Relationship — the surrounding Anchors and Panels both drive the Viewport and are driven by it.
Typical region arrangement:
The activity bar (a narrow leading Anchor) contains tool selectors. Selecting a tool changes the active tool state in the Viewport. The properties Panel (typically trailing) displays properties of whatever is selected in the Viewport — its content is entirely driven by Viewport selection state. The layers or objects Panel (typically leading, in a Panel Group with the activity bar or as a separate Panel) shows the object hierarchy of the canvas and reflects selection state bidirectionally — selecting in the layers Panel selects on the canvas, and vice versa.
The Bidirectional Controller Relationship in Canvas:
| Anchor / Panel | Drives Viewport | Driven by Viewport |
|---|---|---|
| Activity bar (tool selector) | Yes — sets active tool | No |
| Layers / Objects Panel | Yes — selecting a layer selects the object | Yes — selecting an object highlights its layer |
| Properties Panel | No | Yes — displays properties of selected object |
| Zoom control (in header Anchor) | Yes — sets camera zoom | Yes — reflects current zoom level |
Selection states that drive shell changes:
| Selection State | Effect on Shell |
|---|---|
| Nothing selected | Properties Panel shows default / empty state |
| Single object selected | Properties Panel shows that object's properties |
| Multiple objects selected | Properties Panel shows shared/common properties only |
| Group selected | Properties Panel shows group properties; layers Panel expands group |
Minimap: Canvas applications almost always include a Minimap Viewport Fixture, positioned in the bottom-right corner of the Spatial Viewport.
Examples: Figma, Miro, Google Maps, Lucidchart, draw.io, node-based editors (Node-RED, Unreal Blueprint)
Example SDL description — Figma:
Canvas pattern.
Chrome Anchor Span: Top Anchor full-span, all other Anchors inset.
Leading Anchor: activity bar, fixed 48px, drives Viewport tool state → only.
Leading Panel Group: policy: Exclusive, resizable width.
Layers Panel — bidirectional controller
drives and is driven by Viewport selection
Assets Panel — user-initiated
Top Anchor: toolbar, fixed height.
zoom control — bidirectional controller
drives and reflects Viewport camera state
Main Viewport: Spatial mode.
Object model: frame-based
Selection model: multi + hierarchical
Navigation: pan, zoom, fit-to-screen, zoom-to-selection
Viewport Fixture: Minimap, bottom-right corner, user-toggleable
Trailing Panel Group: policy: Exclusive, fixed width 240px.
Design Panel — driven by Viewport selection only
Prototype Panel — driven by Viewport selection only
Inspect Panel — driven by Viewport selection only
Bidirectional controllers:
Layers Panel ↔ Viewport selection
zoom control ↔ Viewport camera state
Chrome corner ownership: Top Anchor owns full width.
Structure: One Viewport containing a grid of independent sub-Viewports (cards or widgets)
Each widget is visually independent and may contain its own content, data, and scroll context. The outer Viewport provides the overall scroll context.
Examples: Analytics dashboards, monitoring tools, home screens
Structure: One Viewport in Staged mode, no persistent Anchors
The entire application surface swaps between discrete states. Common in onboarding flows, wizards, and step-by-step tools.
Examples: Setup wizards, multi-step forms, slide presentations
Structure: No persistent Anchors; one full-screen Viewport; one triggered Anchored Overlay (the command palette)
The application surface is minimal. Primary navigation happens through a keyboard-triggered command palette Overlay.
Examples: Linear (command mode), Raycast, Alfred
How the shell changes is as important as how it is structured at any given moment. SDL defines a vocabulary for shell transitions.
| Transition | Description | Trigger |
|---|---|---|
| Collapse | An Anchor shrinks to its minimum dimension. Adjacent Viewports expand to fill reclaimed space. | User-initiated |
| Lift | An Anchor detaches from the layout and becomes an Anchored Overlay — typically a slide-in drawer. The underlying layout expands to fill the space. | Breakpoint response |
| Swap | One Viewport's content replaces another within the same layout region. The region itself does not change size or position. | Routing or Staged navigation |
| Split | One Viewport divides into two, creating a new scroll context alongside the original. | User-initiated or content-initiated |
| Merge | Two Viewports merge back into one, dissolving one scroll context. | User-initiated or dismissal |
| Inject | A Panel is inserted into the layout, compressing adjacent Viewports. | Trigger (user, content, or state) |
| Eject | A Panel is removed from the layout, and adjacent Viewports expand to fill reclaimed space. | Dismissal |
| Lift Overlay | An Anchored or Modal Overlay appears above the layout. The layout beneath is unchanged. | User-initiated or state-initiated |
| Dismiss Overlay | An Overlay closes. The layout beneath is unchanged. | User action or state change |
An SDL description expresses the full shell architecture of an application in a compact, precise form. It should be readable by both designers and developers and should convey enough information to begin implementation without reference to visual assets.
Start with the named composition, then describe each region in order (top Anchor → leading Anchor → main Viewport → trailing Panel → any Overlays), stating its type, dimension behaviour, Viewport mode if applicable, and controller relationships.
Workspace pattern with Controller.
Chrome Anchor Span: Top Anchor full-span, Leading Anchor inset.
Top Anchor: header, fixed height, full-span.
sidebar toggle — Anchor-to-Anchor controller of Leading Anchor
collapse state, reflects collapse state visually
tab bar — Controller of main Viewport
Leading Anchor: sidebar, collapsible, inset, breakpoint response: Lift.
Anchor Header: workspace switcher
Anchor Body: conversation list, owned scroll
Anchor Footer: User Profile trigger (Anchored Overlay, preferred direction Up)
Invite action (Modal Overlay)
Main Viewport: Staged mode, three stages (Chat, Cowork, Code),
owned vertical scroll per stage.
Trailing Panel: content-initiated trigger (artifact content type),
fixed width, compresses main Viewport on Inject,
user-dismissible.
This description conveys:
- The overall pattern
- Anchor Span — the header is full-span, the sidebar is inset
- The Anchor-to-Anchor controller relationship between the sidebar toggle and the sidebar
- The internal zone structure of the sidebar
- The two Overlay types and their triggers
- The Anchor-to-Viewport controller relationship between the tab bar and main Viewport
- The Panel trigger type and its layout impact
A developer reading this has a clear architectural picture before writing a line of code. A designer reading this can verify it matches their intent. A product manager reading this can understand the structural implications of adding or changing a region.
SDL sits within a broader workflow for application design:
-
App Shell (SDL) — define the structural architecture first, prototype directly in the browser with placeholder content. This is the one layer where designing in a visual tool alone is insufficient — the shell must be experienced in a real browser to understand scroll behaviour, resize behaviour, and responsive mode changes.
-
Design Language — define tokens (colour, spacing, typography, elevation) in parallel. Tokens flow from design tools into SCSS variables, creating a shared vocabulary between design and code.
-
Components in Storybook — build and style individual components in isolation. Components depend on the design language (tokens) and live inside the shell's regions. Storybook bridges component design and component code.
-
Routing and State Architecture — once the shell and key components exist, define how navigation works, how state is shared between regions, and how data flows. Controller relationships identified in the SDL directly inform state architecture decisions.
-
Full Application Assembly — wire components into the shell with real data and real routing. Because the shell is already stable and the components already exist, this is assembly rather than creation.
| Type | Scrolls | Affects Layout | Persistent | Triggered By |
|---|---|---|---|---|
| Chrome | Never | — | Always | — |
| Anchor | Body zone only | Yes | Usually | — |
| Viewport | Yes (owns context) | Yes | Always | — |
| Panel | Optional | Yes (compresses Viewports) | No | Trigger |
| Modal Overlay | Optional | No | No | User/State |
| Anchored Overlay | Optional | No | No | User/State |
| Name | Anchors | Viewports | Primary Use |
|---|---|---|---|
| Workspace | Leading (sidebar) + optional Top | 1 | Productivity tools |
| Master-Detail | Optional | 2 (linked) | List + detail views |
| Canvas | Multiple (tools) | 1 Spatial | Creative tools |
| Dashboard | Optional | 1 + sub-Viewports | Analytics, monitoring |
| Staged | Optional | 1 Staged | Wizards, onboarding |
| Command | None persistent | 1 + Command Overlay | Keyboard-first tools |
Shell Design Language — Draft 1.0 Developed through conversation with Claude, February 2026
The SDL's Panel definition works cleanly when a single Panel is present. When multiple Panels can be open simultaneously — on different edges, or multiple Panels on the same edge — three additional concepts are needed: Panel Group, Panel Policy, and Corner Ownership.
A Panel Group is a named set of Panels that share a layout axis. All Panels within a group compress the Viewport along the same axis (horizontal or vertical).
Properties:
- Axis — horizontal (top/bottom edge) or vertical (leading/trailing edge)
- Position — which edge the group occupies (leading, trailing, top, bottom)
- Policy — how multiple Panels within the group coexist
- Minimum Viewport dimension — the smallest the Viewport may be compressed to before the policy changes or Panels are forcibly ejected
An application may have multiple Panel Groups on different edges simultaneously. This is where Corner Ownership becomes necessary.
Panel Policy governs how multiple Panels within a single Panel Group coexist:
| Policy | Description | When to use |
|---|---|---|
| Exclusive | Only one Panel may be open at a time. Opening a second automatically ejects the first. | Panels serve similar purposes and shouldn't compete for space. Simplest to implement. |
| Additive | Multiple Panels may be open simultaneously, each taking its defined size. Viewport is compressed by the sum. Requires a minimum Viewport dimension — below which the policy falls back to Exclusive. | Panels show genuinely different content users need in parallel. |
| Tabbed | Multiple Panels share one fixed-size layout region with a tab bar to switch between them. Layout footprint is always one Panel wide/tall regardless of how many are available. | Many Panels are possible but screen space is limited. Common in IDEs. |
When Panel Groups on two different axes are simultaneously active, they meet at a corner of the Viewport. That corner must be owned by exactly one group. Corner Ownership must be explicitly specified — it is not a visual preference but a structural decision with CSS Grid implementation consequences.
| Owner | Result |
|---|---|
| Horizontal group owns corner | Bottom (or top) Panel Group runs the full width inside the Anchors. Vertical Panel Group stops at the edge of the horizontal group. |
| Vertical group owns corner | Trailing (or leading) Panel Group runs the full height inside the Anchors. Horizontal Panel Group fills only the remaining width. |
Corner Ownership is a property of the Chrome, not of the Panel Groups. It is specified once and must be decided before building the root grid. Changing it later requires reworking the Chrome layout.
When multiple Panel Groups are active, the Viewport's available dimensions are:
Viewport width = Chrome width − leading Anchor − leading Panel Group − trailing Panel Group
Viewport height = Chrome height − top Anchor − bottom Anchor − bottom Panel Group
These calculations must be maintained in application state, because they inform when to trigger policy fallbacks, when to warn about insufficient space, and how to restore Panel states on reopen.
Canvas pattern (adapted — main Viewport is Staged, not Spatial).
Chrome Anchor Span: Top Anchor full-span, all other Anchors inset.
Leading Anchor: activity bar, fixed 48px.
tool selectors — Anchor-to-Panel-Group controller of Leading Panel Group
Leading Panel Group: policy: Exclusive, resizable width.
Explorer — user-initiated via activity bar
Search — user-initiated via activity bar
Source Control — user-initiated via activity bar
Extensions — user-initiated via activity bar
Top Anchor: tab bar, fixed height.
Main Viewport: Staged mode (open editor tabs), owned scroll per tab.
Bottom Panel Group: policy: Tabbed, resizable height.
Terminal — user-initiated
Output — state-initiated
Problems — state-initiated
Chrome corner ownership: Bottom Panel Group owns full width.
Trailing Panel Group: policy: Additive, minimum Viewport width: 400px.
Artifact Panel — content-initiated, fixed 380px
References Panel — user-initiated, fixed 280px
Bottom Panel Group: policy: Exclusive.
Terminal Panel — user-initiated, resizable 200–400px
Output Panel — state-initiated, fixed 240px
Chrome corner ownership: Bottom Panel Group owns full width.
Shell Design Language — Draft 1.2 Anchor Span and Anchor-to-Anchor Controller Relationship added February 2026