Context
Mobile horizontal scroll recurred repeatedly on the console. Root cause (fixed in 5fbbff1): every page-root container was max-w-[N] mx-auto … without w-full. As flex items of the flex-col <main>, mx-auto disables cross-axis stretch, so each container sized to max-content (~634px) instead of the viewport and put a horizontal scrollbar on <main> — across Dashboard, AgentDetail, Profile, Browse, Notifications, Usage, Terminals, RunDetail, and RepoTab.
5fbbff1 fixed the 10 existing copies, but the pattern is hand-copied per page, so the next new page will drop w-full again. This issue removes the footgun at the source.
Proposal
A single shared container component (or class constant) that bakes in the correct pattern, used by every page root:
// components/Page.tsx
export function Page({ width = 960, className = "", children }: { width?: 960 | 1040 | 1100; className?: string; children: React.ReactNode }) {
return <div className={`w-full max-w-[${width}px] mx-auto px-3 py-3 sm:px-6 sm:py-5 ${className}`}>{children}</div>;
}
(Tailwind can't interpolate arbitrary values at runtime — use a small map of the 3 widths to static classes, or a CVA/clsx variant, so the classes are statically present for the JIT.)
Then each page returns <Page>…</Page> instead of re-typing the div.
Critical assessment
- This is the root-cause fix (single source of truth) — strictly better than the two alternatives considered:
- A global
html,body{overflow-x:hidden} net was rejected: it hides the symptom (content silently clips off-screen), can break position: sticky, and trains nobody to write the correct pattern. Keep at most as commented defense-in-depth, never as the primary fix.
- Fixing the 10 copies (done in
5fbbff1) stops today's bug but not the next new page.
- Scope caveat: full-height pages (InstanceDetail and its tabs) do NOT use this
mx-auto pattern — they use a flex-1 min-h-0 full-bleed layout and must NOT be converted to <Page>. This component is only for the centered, scrollable pages.
- Tailwind v4 note: the sibling footgun for flex children that refuse to shrink is a missing
min-w-0 (and min-h-0); worth a one-line comment in the component pointing at both.
Acceptance criteria
Refs: 5fbbff1 (the 10-copy fix this supersedes). Pairs with the CI overflow test (companion issue).
Context
Mobile horizontal scroll recurred repeatedly on the console. Root cause (fixed in
5fbbff1): every page-root container wasmax-w-[N] mx-auto …withoutw-full. As flex items of theflex-col<main>,mx-autodisables cross-axis stretch, so each container sized tomax-content(~634px) instead of the viewport and put a horizontal scrollbar on<main>— across Dashboard, AgentDetail, Profile, Browse, Notifications, Usage, Terminals, RunDetail, and RepoTab.5fbbff1fixed the 10 existing copies, but the pattern is hand-copied per page, so the next new page will dropw-fullagain. This issue removes the footgun at the source.Proposal
A single shared container component (or class constant) that bakes in the correct pattern, used by every page root:
(Tailwind can't interpolate arbitrary values at runtime — use a small map of the 3 widths to static classes, or a CVA/clsx variant, so the classes are statically present for the JIT.)
Then each page returns
<Page>…</Page>instead of re-typing the div.Critical assessment
html,body{overflow-x:hidden}net was rejected: it hides the symptom (content silently clips off-screen), can breakposition: sticky, and trains nobody to write the correct pattern. Keep at most as commented defense-in-depth, never as the primary fix.5fbbff1) stops today's bug but not the next new page.mx-autopattern — they use aflex-1 min-h-0full-bleed layout and must NOT be converted to<Page>. This component is only for the centered, scrollable pages.min-w-0(andmin-h-0); worth a one-line comment in the component pointing at both.Acceptance criteria
<Page>component with the 3 supported max-widths as static classes.max-w-[N] mx-autopage roots remain (grepclean).Refs:
5fbbff1(the 10-copy fix this supersedes). Pairs with the CI overflow test (companion issue).