# Strata approved layouts

> The product app's macro layout doctrine lives in
> **`apps/web-v2/docs/AGENT_APP_UI_CONVENTIONS.md`** (chat ↔ canvas ↔ sheets —
> read it for anything touching the chat surface). This doc is the index of
> approved page-level shapes; if the shape you need isn't here, propose a new
> one — don't improvise a bespoke layout.

## The surface model

The product surface is **chat + canvas + sheets**. Chat is text and buttons
only; everything else renders on the canvas as sheets. The chat column is the
bounded resizable element (min 280, max 816); the canvas takes the rest.

## Sheet types — pick by contract

| Surface | Component | Use for |
|---------|-----------|---------|
| Canvas sheet | `CanvasSheet` | An artifact rendered full on the canvas. Stacks up to 3 deep with progressive recede; base sheet stays mounted. |
| Inspector panel | `WindowSheet` | Right-anchored resizable inspector/editor (min 400px). |
| Wall | `Dialog` / `AlertDialog` | Auth, paywall, destructive confirm — blocking, no artifact behind it. |
| Fullscreen editor | `FullscreenModal` | Creative builders and editors. |

Stock shadcn `Sheet` is never used directly.

## CanvasSheet — the law

- **Overlays are stacked CanvasSheets.** Any overlay/detail view in a product
  area is a sibling `CanvasSheet` stacked above the base sheet — never a
  modal, never a nested child. `stackedDepth` on the sheet below controls the
  recede.
- **Headers are the standard sub-components, never hand-rolled JSX:**
  - `CanvasSheetChrome` — sticky header for tabbed/toolbar sheets
    (`NavTabs` + optional `CanvasSheetToolbar`).
  - `CanvasSheetHeader` — eyebrow + title + actions for chrome-less sheets.
  - Vertical rhythm between chrome, toolbar, and `CanvasSheetBody` is
    automatic — never add manual `pt-*`/`pb-*`/`gap-*` between them.
- Which sheet is open lives in URL search params or layout state, not in the
  page component.
- No close behavior destroys underlying state — dismissing a top sheet lands
  exactly where the user left the sheet below.

## WindowSheet — the composition

Right-anchored resizable inspector on Base UI Dialog (drag the left edge;
`defaultWidth`/`minWidth`/`maxWidth` on `WindowSheetContent`, max defaults to
90% of viewport).

- `WindowSheetHeader` children are the LEFT side (tabs or title); the
  `actions` prop is the RIGHT side (icon-only buttons). Header and footer are
  both 64px min-height, content centered.
- `WindowSheetBody` is the scroll region — always use it, never a hand-rolled
  `flex-1 overflow-y-auto`. `WindowSheetSection` provides the padding;
  `variant="secondary"` tints a region. Forms inside are bare `<form>` +
  `FieldSet`.
- `WindowSheetTitle` is required by the a11y contract — `className="sr-only"`
  when the header shows tabs instead of a visible title.

## Area pages (product app)

- Area navigation is `NavTabs` inside `CanvasSheetChrome`; filters are
  toolbar controls bound to **URL search params** (shareable state), all
  `size="sm"` (32px). Filter selects are text label + chevron only (no icons
  inside `SelectTrigger`); view toggles are `TabsList size="sm"` with text
  labels when an icon alone would be ambiguous.
- **`DataTable` is the one table.** Every tabular surface uses it (sticky
  header, mono uppercase `<th>`, keyset-paginated data underneath — list
  APIs are cursor-based, never offset).
- Grids use the shared grid classes — never a new one-off grid:

  | Class | Lives in | Min column | Context |
  |-------|----------|-----------|---------|
  | `content-grid` | `packages/ui/src/css/canvas-sheet.css` | 240px | Generations page, content picker sheet |
  | `library-grid` | web-v2 `client/css/influencer-card.css` | 272px | Library pages (influencers, media, products) |
  | `builder-grid` / `builder-grid-sm` | web-v2 `client/css/creative-builder.css` | 240px / 180px | Builder detail views inside `FullscreenModal` |

## Sheet footers

At most two actions: the primary (does the thing the sheet is about) and
**Discuss with Elle** (always secondary, right-aligned, mono uppercase
subtle style — closes the sheet and drops the artifact into the composer as
context).

## Marketing pages

Page shells and section building blocks are listed in `brand.md` — content
pages compose from `ContentLayout` + the section kit, never bespoke section
scaffolding.