# Inbox — design-sweep dossier

**File:** `apps/web/src/routes/Inbox.tsx` (834 lines, single file — layout + all
pane styles inline as `React.CSSProperties` objects, no separate CSS file).
Reached via `App.tsx` route `/inbox`; comments cite `appshell scope 2 Stage 3`
and `Tile D` — this screen already went through at least one rethink pass.

**Legacy markers:** 22 (pinned in `LEGACY_BASELINE["routes/Inbox.tsx"]`) — low
for an 834-line screen, and the two I could attribute by hand are both
hardcoded `rgba(10, 31, 68, 0.42/.25)` scrim/shadow colors (lines 770, 780) —
navy literals, not `--cm-*` tokens, in the bottom-sheet overlay. The rest of
the file is consistently on `var(--cm-*)`.

**Raw form controls:** 3 `<input>` (search text, "Failed sends only"
checkbox, "Templates only" checkbox) + 1 `<select>` (channel filter) — all
unstyled-by-design-system native elements with manual token-based inline
styling, no shared Input/Select/Checkbox primitive.

## Five lenses

- **IA / concept count** — high, but proportionate to an inbox's job: 3
  panes (list, chat, lead context) × per-pane filters (search, failed-only,
  channel, templates-only) × per-message state (window open/closed, direction
  mark, inline detail panel) × responsive pane-to-navigation swap below the
  shell boundary. A first-time user holds 6-7 live concepts at once. This is
  inherent to "investigative inbox," not accidental complexity — trimming it
  would remove real capability.
- **Interaction** — solid: QueryState-driven loading/empty/error states, live
  polling (15s list / 8s open thread), cursor pagination, inline detail panel
  instead of a covering overlay, explicit mobile pane-navigation with Esc-to-
  close on the bottom sheet. Gap: the bottom sheet (`role="dialog"`, lines
  410-431) has no `aria-modal="true"` and no focus trap/return-focus — Esc and
  scrim-click close it, but focus can tab out to background content while
  open.
- **Content / copy** — "Window open / Window closed" (lines 253, 318) is Meta
  Business API jargon (the 24-hour customer-service messaging window) surfaced
  verbatim as user-facing copy, no plain-language gloss. Everything else reads
  as plain words ("Failed sends only," "Templates only," "Select a
  conversation to investigate").
- **Visual / tokens** — mostly clean: entirely `var(--cm-*)` except the two
  hardcoded navy `rgba()` literals in the bottom-sheet scrim/shadow (770,
  780) — the exact navy the tokens law calls dead in product UI. Inline
  `style={}` objects for the whole layout (not CSS classes) is the file's
  structural pattern; consistent within the file, but out of step with
  wherever else the sweep has landed on `--cm-*` CSS files instead.
- **A11y / responsive** — better than average: aria-labels on the search
  input, channel select, back/close/detail buttons; `aria-current` on the
  active row; `aria-expanded`/`aria-controls` on the mobile Details toggle.
  Explicit sub-shell-boundary redesign (list-as-screen → chat-with-back →
  lead-context-as-bottom-sheet) already handles narrow viewports as a real
  layout change, not squeeze-and-hope. The one hole is the dialog focus trap
  noted above.

## Verdict: **polish**

This is a daily-use, live, already-rethought screen with the lowest legacy-
marker density of any screen in this group and structurally sound responsive
and loading-state handling. The remaining issues are targeted: two hardcoded
navy literals to retoken, one jargon string to reword, one focus-trap gap to
close, and a decision on whether the native form controls should move onto
shared Input/Select/Checkbox primitives. None of that requires touching the
IA or the pane structure — a redesign would be spending risk on a screen that
does not need it.

## Forks

1. **"Window open / Window closed" wording** — keep the literal Meta term
   (accurate, but jargon to a first-time reader) or replace with a plain-
   language equivalent (e.g. "Can reply now" / "Reply window closed")? My
   recommendation: reword — this is the one copy spot where engineering
   vocabulary leaked into product UI.
2. **Native form controls → shared primitives** — is there (or should there
   be) a house Input/Select/Checkbox component these 4 controls should adopt,
   or do they stay hand-styled per screen until the headless behavior layer
   lands? My recommendation: hold until the behavior-layer decision is made
   project-wide, don't special-case Inbox.
3. **Bottom-sheet focus trap** — worth a dedicated a11y fix now (small,
   isolated), or bundled into whatever composite-dialog work the headless
   layer brings? My recommendation: fix now, it's a few lines and a real gap
   for keyboard/screen-reader users.
