simocracy-v2 · modal-cutoff-audit
Prompted by a user-reported cutoff on the Create New Sim dialog, I walked agent-browser through every reachable modal on prod at a realistic 13-inch viewport (1280×577) and measured child-element overflow against the dialog bounding box with a DOM probe. Three real clipping bugs, two structural risks, the rest pass.
Headline. The reported Create New Sim cutoff reproduces — the right-hand column (name field, reset row, save button) overflows DialogContent by 79 px. Two other modals fail the same test: Connect to Agent overflows both the top and bottom of the viewport with no internal scroll, and the FTC S-Process run view's tab strip clips 🔍 Disagreement at the right edge. Two additional surfaces pass the automated probe but have layout risks worth flagging — the FTC proposal-detail modal lets a 16:10 hero image eat 85% of dialog height, and two smaller DialogContents ship with neither max-h-[90vh] nor overflow-y-auto, so they'd clip silently on shorter viewports.
Signed in once as satyam2.climateai.org, then walked each surface that opens a modal: /my-sims (create/edit sim, delete), sim profile (chat, interview, connect to agent, edit constitution, edit style), /events (create event, author template, allocation picker), /senate (building sidebar, submit proposal, start discussion), /ftc-sf (floor sidebar, submit proposal, proposal detail, S-Process). For each open dialog I ran a DOM probe that captured the dialog's bounding rect and walked every descendant's getBoundingClientRect(), flagging anything whose right edge extended >4 px beyond the dialog's right edge — i.e. the actual definition of a cut-off button — and separately logging dialogs whose content extended below the viewport with no internal scrollbar.
Opening + Create New Sim from /my-sims renders a two-column layout where the right column (Sim Name input, the ↩ Reset / 🔄 Reset Colors / 🎲 Randomize button row, and the Save to ATProto button) spills 79 px past the dialog's right edge. The Randomize pill is visibly truncated to “RAN…” and Save to ATProto's right edge hits the dialog border.
Root cause: components/avatar/avatar-editor.tsx — the right column uses flex-col gap-3 flex-1 w-full without min-w-0, and the reset-button row flex gap-2 has three pills at fixed intrinsic width with no wrapping. The outer grid uses the avatar preview at intrinsic size and lets the right column absorb the remainder, which becomes negative when the viewport is 1280 px.
Probe output:
overflowers = [
{ tag: 'div', txt: 'Sim Name0/64 characters↩ Reset…', overR: 79, cls: 'flex flex-col gap-3 flex-1 w-full' },
{ tag: 'input', txt: '', overR: 79 },
{ tag: 'div', txt: '↩ Reset🔄 Reset Colors🎲 Randomize', overR: 79, cls: 'flex gap-2' },
{ tag: 'button', txt: '🎲 Randomize', overR: 79, cls: 'whitespace-nowrap…' },
{ tag: 'button', txt: 'Save to ATProto', overR: 79 }
]
Fix candidates (non-prescriptive):
min-w-0 to the right column so it can actually shrink inside the flex container.flex-wrap, or use shorter copy (e.g. drop the emojis, use Reset / Colors / Random).Opening Connect to Agent from a sim profile produces a dialog that is 601 px tall in a 577 px viewport, with no internal scroll. Its top is rendered at y = -12 (header clipped) and bottom at y = 589 (“Full heartbeat routine” link clipped). The dialog title and the sign-in steps are both partially off-screen on this viewport.
Root cause: components/sim/sim-profile.tsx:506 ships <DialogContent className="max-w-lg"> with no height cap and no scroll container. The content is three numbered steps plus two code blocks; perfectly reasonable, but cumulatively taller than a short laptop viewport.
Fix candidate: match the convention used by most other modals — className="max-w-lg max-h-[90vh] overflow-y-auto".
Inside the FTC S-Process modal, opening a past run renders a horizontal tab strip with one tab per recommender sim plus Results and 🔍 Disagreement. On a 1280 px viewport the tab strip doesn't wrap, doesn't scroll, and the rightmost 🔍 Disagreement pill overflows by 22 px, rendering as “🔍 Disagreeme”. With more recommenders the overflow will grow.
Fix candidates: add overflow-x-auto with custom scrollbar styling to the tab strip, let the tab row flex-wrap, or stash overflowing tabs behind a More… popover.
The FTC floor proposal-detail modal (components/ftc-sf/proposal-detail-modal.tsx) renders a max-h-[85vh] glass panel whose first child is a aspect-[16/10] hero image. On a 577 px viewport: panel height 490 px, hero height 419 px. The proposal title is almost entirely below the fold on first open — the user sees a big gray placeholder and an X button and has to scroll to discover what they clicked. The gathering proposal-detail modal in gathering-world.tsx:945 uses the same pattern and has the same issue.
Fix candidates: cap the hero at max-h-[30vh] or max-h-[200px], use aspect-[21/9], or swap the order so the title sits above a smaller banner strip.
Static grep of the codebase found two DialogContents that ship with neither a height cap nor overflow-y-auto, meaning any future content growth will clip silently on short viewports:
components/sim/hypercerts-panel.tsx:116 — Create Evaluation — sm:max-w-md.components/ftc-sf/proposal-form-dialog.tsx:221 — FTC Submit Proposal — sm:max-w-xl. Currently 570 px tall in the 577 px viewport — already 1 px from clipping, no slack.Fix candidate: apply the house standard — max-h-[90vh] overflow-y-auto — to both.
max-h-[90vh] overflow-y-auto. Probe: 0 overflowers.
max-h-[80vh] flex column.
max-h-[90vh] overflow-y-auto does its job; internal scroll container is 1723 px inside a 517 px dialog.
| Modal | File | DialogContent class | Status |
|---|---|---|---|
| Create New Sim / Edit Appearance | components/sim/appearance-editor-dialog.tsx | sm:max-w-3xl max-h-[90vh] overflow-y-auto | clipped |
| Edit Constitution | components/sim/agents-editor-dialog.tsx | sm:max-w-2xl max-h-[90vh] overflow-y-auto | pass |
| Edit Speaking Style | components/sim/style-editor-dialog.tsx | sm:max-w-2xl max-h-[90vh] overflow-y-auto | pass |
| Chat with … | components/sim/sim-chat-modal.tsx | sm:max-w-lg max-h-[80vh] flex flex-col … | pass |
| Interview Mode | components/sim/interview-modal.tsx | sm:max-w-lg p-0 gap-0 overflow-hidden | pass |
| Connect to Agent | components/sim/sim-profile.tsx | max-w-lg | clipped |
| Create Evaluation | components/sim/hypercerts-panel.tsx | sm:max-w-md | risk |
| Start Discussion | components/sim/sim-discussion-modal.tsx | sm:max-w-2xl max-h-[85vh] flex flex-col … | pass |
| Create / Edit Event | components/events/gathering-form-dialog.tsx | max-w-lg max-h-[90vh] overflow-y-auto | pass |
| Author a new template | components/events/template-author-dialog.tsx | max-w-lg max-h-[85vh] overflow-y-auto | pass |
| Submit Proposal (Senate) | components/events/gathering-proposal-form.tsx | max-w-lg max-h-[90vh] overflow-y-auto | pass |
| Proposal detail (gathering) | components/events/gathering-world.tsx:945 (portal) | max-w-2xl max-h-[85vh] overflow-y-auto + 16:10 hero | hero 85% |
| Select Allocation Mechanism | components/events/gathering-form-dialog.tsx (portal) | — | pass |
| FTC Submit Proposal | components/ftc-sf/proposal-form-dialog.tsx | sm:max-w-xl | risk |
| FTC Proposal detail | components/ftc-sf/proposal-detail-modal.tsx (portal) | max-w-2xl max-h-[85vh] overflow-y-auto + 16:10 hero | hero 85% |
| FTC S-Process | components/ftc-sf/ftc-s-process-modal.tsx | sm:max-w-4xl max-h-[85vh] flex flex-col … | tab clipped |
| Generic S-Process | components/s-process/s-process-modal.tsx | sm:max-w-4xl max-h-[85vh] flex flex-col … | same shared tab pattern |
| MVF Detail | components/s-process/mvf-detail-modal.tsx | sm:max-w-2xl max-h-[90vh] overflow-y-auto | not triggered |
| Past Hearing / Senate Hearing | components/senate/…-modal.tsx | sm:max-w-2xl max-h-[85vh] flex flex-col … | not triggered |
| Floor Lead Editor | components/ftc-sf/floor-lead-editor.tsx | sm:max-w-md | facilitator-only |
| Delete Sim | components/my-sims/sim-character-card.tsx (AlertDialog) | default | pass |
| Sign-in popover | components/navbar.tsx | Radix popover | pass |
satyam2.climateai.org · DID did:plc:cpoagodpqrgs4t7thi5z37uf · PDS climateai.org
Viewport1280×577 (13-inch MacBook-ish laptop)
Date2026-04-22
Toolingagent-browser open <url> → agent-browser eval <probe.js> → agent-browser screenshot.
ProbeFor each [role=dialog], walk querySelectorAll('*') and flag any descendant whose getBoundingClientRect().right exceeds the dialog's right by >4 px; also log dialog bottom edge vs innerHeight and whether scrollHeight > clientHeight.
Screenshotsassets/01–27-*.png
Net recommendation for eng. Three quick fixes unblock most of this: (1) add min-w-0 and let the reset-button row wrap in avatar-editor.tsx; (2) apply the house-standard max-h-[90vh] overflow-y-auto to the three outliers (sim-profile.tsx:506, hypercerts-panel.tsx:116, proposal-form-dialog.tsx:221); (3) make the FTC S-Process tab strip scroll horizontally or wrap. The hero-image-too-tall finding on proposal-detail modals is cosmetic but noticeable enough on a 13-inch laptop that I'd cap the hero at ~200 px and put the title above the fold.