Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

console: a screen flow renders every screen in a fixed 448px single-column dialog, so a long screen pushes its Submit below the viewport on a 1440px display (17.7.0) #12080

Closed

Description

@objectstack-fleet

Filing class: ① product defect (user-visible) — reach: browser, measured once on 17.7.0. Maintainer instruction for platform problems found in the hotclm browser test, verbatim, 2026-10-10: 「你遇到的平台问题应该提交issue」.

Reader: objectui triage → the console's screen-flow runner (the dialog that hosts a flow screen).

Symptom

Measured in objectstack-ai/hotclm during its full browser pass on @objectstack/* 17.7.0 (objectstack-ai/hotclm#87, main @ c31c7e2), Chromium 1194, viewport 1440×900, signed in as a business requester launching the app's intake screen flow (contract_intake).

  • The screen dialog measures 448px wide (on screen x=496–944) — exactly Tailwind's max-w-md — and stays 448px however wide the window is. Every field renders in one column.
  • The intake flow's second screen carries 13 fields (title, signing entity, department, amount, currency, estimate flag, start/end date, term, summary, governing law, confidentiality term, …). In a 448px single column it is taller than the viewport: the Submit / Next button sits below the fold, and the user has to discover that the overlay scrolls. Screenshot: qa/browser-test-17-7/screenshots/18-finding-intake-step2-submit-below-viewport-after-wheel.png on branch claude/issue-87-browser-test-17-7 of objectstack-ai/hotclm (taken after a mouse-wheel scroll; the page behind is dimmed, two thirds of the screen unused).

Expected

A screen dialog sized to its content — wider on wide displays, or a multi-column layout for long screens, as record forms already get — with the primary action always reachable (sticky footer). The app cannot change this: the screen spec carries no width or layout hint for the dialog, and splitting the screen in two just to fit a fixed width would be an app-side workaround of a platform limit.

Dedupe

MCP search_issues on objectstack-ai/objectui, query flow screen dialog fixed narrow width max-w-md submit button below viewport long screen → 5 hits, none on the flow runner: #620 / #705 / #679 / #618 (closed, Feb 2026 — ModalForm record-form dialogs), #11795 (closed — Studio below tablet width).


Filed by the repo:hotclm PM seat from a measured browser finding.

Activity

  1. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Additional evidence from the same hotclm pass (objectstack-ai/hotclm#87, 17.7.0, 1440×900) · 2026-10-10T02:37Z — the dialog is not only narrow, it does not scroll:

    • Intake flow screen 2: dialog height 1184px, top -142px, bottom 1042px, overflow-y: visible; the Submit button sits at y=977 and ten mouse.wheel ticks move nothing; the heading is clipped off the top (screenshots 016, 018). A mouse user cannot reach Submit; keyboard focus + Enter can.
    • The same layout hosts action parameter dialogs: "Backfill Executed Contract" (a params list) measures height 2198px, top -649px — its first five required fields sit above the top edge (111, 112).
    • ScreenConfigSchema (strict) carries no layout / columns / width key, so metadata cannot ask for a different size; object create/edit forms, by contrast, render two columns and scroll (050, 081).

    Repro: any flow screen node or action params list longer than ~12 fields on a 900px-high viewport. Screenshots are under qa/browser-test-17-7/screenshots/ on branch claude/issue-87-browser-test-17-7 of objectstack-ai/hotclm.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade, bug · priority:p2 · domain:ui · area:workflow · pm:queue

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-10T03:56Z. ⛔ Not a claim, ⛔ not a dispatch.

    • Re-read on objectui main 1b2d0160fe: packages/app-shell/src/views/FlowRunner.tsx:537 gives an object-form screen sm:max-w-3xl max-h-[90vh] overflow-y-auto, but every other screen gets sm:max-w-md with no height bound and no scroll. That matches the measurement: a long screen overflows the viewport and does not scroll.
    • Why p2: a mouse user cannot reach Submit on a long screen or a long action-parameter list, and required fields can sit above the top edge. Keyboard focus still works, so it is not a total block.
    • Direction:
      1. Reach first: every screen and parameter dialog is height-bounded and scrolls, with a footer that keeps the primary action visible. That is the same bound the object-form branch already has.
      2. Width: the dialog widens with its content, for example two columns on wide displays for long screens, as record forms do. That is the renderer's choice.
      3. ⛔ No new spec layout key. Nothing beyond this card pulls for it, and the renderer can size by content.
    • Pins: a 13-field screen and a long params dialog on a 900px-high viewport both have their primary action reachable without the keyboard. Control: a short screen is unchanged.
  3. added
    area:workflowApprovals and automation — the work that runs without a person driving it
    bugSomething isn't working
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Oct 10, 2026
  4. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1
    Session: session_01B1gHb9baeX7oioD5sHVm7z
    Account: marchtian
    Branch: claude/issue-12080-screen-dialog-reach
    Worktree: objectui-issue-12080
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/app-shell/src/views/FlowRunner.tsx (the screen dialog's sizing and footer), packages/app-shell/src/views/ActionParamDialog.tsx (the parameter dialog's sizing and footer), and their tests (stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default tier — dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate"
    Clause-②: no
    Responsibility: objectui's app-shell FlowRunner.tsx, whose non-object-form screens get a fixed sm:max-w-md dialog with no height bound and no scroll (and the parameter dialog's layout) | the object-form branch of the same dialog already bounds and scrolls, so the platform path exists and the other screens do not take it | every user of a flow screen or a long action-parameter list, measured on objectstack-ai/hotclm#87 (17.7.0, 1440x900)
    Thread-read: 6093518840
    Serial constraints cleared: none. No in-flight card touches FlowRunner.tsx or ActionParamDialog.tsx; ActionParamDialog.tsx was last changed before 2026-10-10.

    Clause-② is no: the fix changes layout classes and the footer's placement. It adds no prop, no export and no locale key, and triage ruled out a new spec layout key.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 12080,
      "status": "done",
      "branch": "claude/issue-12080-screen-dialog-reach",
      "pr": "https://github.com/objectstack-ai/objectui/pull/12088",
      "session": "session_01B1gHb9baeX7oioD5sHVm7z (subagent mode: the parent seat's id)",
      "premise_still_valid": true,
      "summary": "Premise confirmed in Chromium at BASE 023f00d (1440x900): the 13-field flat screen dialog measured 448x1218, top -159, overflow-y visible, no scroll container, Submit at y 994-1034, ten wheel ticks moved nothing. The 22-param ActionParamDialog measured 512x1868, top -484. Both PM mechanism assumptions held. (1) FlowRunner's non-object-form branch is the whole screen defect: its footer is a direct child of an unbounded DialogContent. (2) ActionParamDialog is the same shape on the bare DialogContent; the default in @object-ui/components ui/dialog.tsx has no height bound and is the Shadcn no-touch zone. Fix, in the two consumers only: DialogContent becomes 'flex max-h-[90vh] flex-col'. The field region is the one scrolling element ('-mx-6 min-h-0 flex-1 overflow-y-auto px-6'), and the footer sits outside it. More than 8 declared screen fields, or more than 8 shown params, adds sm:max-w-3xl (the object-form width) and a sm:grid-cols-2 grid. Shorter screens and lists keep sm:max-w-md and the default max-w-lg in one column. The object-form step keeps sm:max-w-3xl plus the bound; its scroll moved from the whole dialog into the body, so its heading and close X now stay in view. The failure and refusal Alerts stay above the body and are now always in view. No prop, export, locale key or spec key: Clause-② stays no. ScreenView is not edited; the grid classes go through its existing className.",
      "tests": "Chromium proof, final run at HEAD ca44673. Scratch harness served by the console's own Vite config (never committed, deleted). Real mouse.wheel x10 and real mouse.click, Chromium 1194. At 1440x900: 13-field screen 768x762, 2 columns, Submit 766-806 in viewport, hit-test true, click produced the required-fields toast. 22 params 768x810, body 644/932, wheel scrollTop 0 to 288, Confirm clicked, 3 required errors shown. Controls identical to BASE: 3-field screen 448x402 top 249, 2 params 512x338 top 281. 1366x768 and 390x844: every primary action in viewport, hit-tested and clicked. Threshold at 1440x900: 8 fields narrow 448x778 with body 616/616 (fits), 9 fields wide 768x562. Unit: pnpm exec vitest run --maxWorkers=2 on the 24 affected files (9 FlowRunner*, FlowRefusalNotice, 9 ActionParamDialog*, 3 ScreenView*, 2 paramDialogTitle consumers) gave Test Files 24 passed (24), Tests 206 passed (206); the 2 new files hold 15 tests. Reverse verification from the committed fix: git checkout 023f00d on both sources (disk: isLongScreen 3 to 0, isLongList 3 to 0, max-h-[90vh] 0) made Tests 15 failed (15), Test Files 2 failed (2). Restored with git checkout HEAD: blobs 481cb37d / f409340c equal HEAD, git diff HEAD empty, index clean. Caveat: the control cases fail on BASE because the body testid they read is absent there; the unchanged control width is shown by the browser rows. pnpm --filter @object-ui/app-shell type-check exit 0, after building the dependency closure; tsconfig.test.json includes src/**/*.test.tsx. All local runs went through os-verify-lock; lock seconds are shared-box figures.",
      "mcp_calls": "0",
      "api_writes": "3 — all through the scripts/pm fleet-write relay as objectstack-fleet[bot], each one POST /repos/objectstack-ai/objectstack/dispatches: (1) pr_create, POST /repos/objectstack-ai/objectui/pulls, opened draft #12088, body read back identical at 9338 bytes; (2) label-write --assign marchtian, POST /repos/objectstack-ai/objectui/issues/12088/assignees, read back MATCHES, zero label writes; (3) this os-dev-report comment, POST /repos/objectstack-ai/objectui/issues/12080/comments. Plus git push (not REST).",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — other console dialogs on the bare DialogContent also have no height bound. Read-only inference, not measured: most show short fixed content. Recorded in the PR's Acceptance notes with the instrument (git grep DialogContent, read per call site)."
      ],
      "gates": [
        "pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' build: exit 0",
        "pnpm --filter @object-ui/app-shell type-check: exit 0",
        "pnpm exec vitest run --maxWorkers=2 (24 affected files): Test Files 24 passed (24), Tests 206 passed (206)",
        "eslint --format json on the 4 touched files: 4 files, 0 errors, 16 warnings, all on untouched lines. Population: app-shell lint is eslint . Invariance: eslint.config.js sets no parserOptions.project or projectService, so type-aware linting is off and this diff cannot move an untouched file's verdict. Run at ca44673.",
        "pnpm check:new-line-citations: VERDICT 0 new citation(s), exit 0",
        "pnpm check:control-bytes: OK, exit 0",
        "node scripts/check-changeset-presence.mjs: 1 changeset declared, exit 0",
        "node scripts/check-changeset-no-major.mjs: exit 0",
        "pnpm check:changeset-claims / check:pending-changeset-literals / check:i18n-keys / check:test-path-roots / check:unreferenced-sources: all exit 0",
        "NOT MEASURED: check:eager-closure. Reason: it needs a full console production build. No module joins the closure: the new imports are cn from @object-ui/components and screenFields from ./ScreenView, both already imported. The byte delta is the added class literals and is declared to CI Bundle Analysis.",
        "CI at ca44673 when reported: 42 check runs, 24 completed with 0 failures, 18 in_progress"
      ],
      "line_budget": "+396 / -38 over 5 files. Source: FlowRunner.tsx +83/-36, ActionParamDialog.tsx +34/-2. Tests: +141, +127. Changeset: +11. No skills/** or governed surface touched.",
      "deviations": [
        "Reach proof is a one-off recorded in the PR body, not a committed e2e spec. The PM left this to me. The repo's geometry e2e lane builds no workspace dist and refuses workspace imports by name, so a committed spec would have needed stubs for most of FlowRunner's import graph. The scratch harness instead mounted the real components through the console's own Vite aliases.",
        "check:eager-closure not run (declared NOT MEASURED above)."
      ],
      "files_changed": [
        ".changeset/12080-screen-dialog-reach.md",
        "packages/app-shell/src/views/FlowRunner.tsx",
        "packages/app-shell/src/views/ActionParamDialog.tsx",
        "packages/app-shell/src/views/__tests__/FlowRunner.dialogReach-12080.test.tsx",
        "packages/app-shell/src/views/ActionParamDialog.dialogReach-12080.test.tsx"
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR objectui#12088 (head ca446737ee) · domain:ui seat 3, session_01B1gHb9baeX7oioD5sHVm7z, 2026-10-10T09:29Z

    Reviewed against GitHub and the diff, not the report (6096122941).

    • Shape:
      • The PR is a draft on main.
      • Its first line is Fixes #12080, and Clause-②: no sits at the start of a line.
      • No other card number sits near a closing keyword.
      • The assignee is marchtian, mirroring the card.
    • Scope: 5 files, +396/−38: the two dialogs, two new test files and one changeset. Nothing touches content/docs/releases/, and no file is unrelated to the card.
    • Governed surface: scripts/check-governed-queue-guard.mjs --test over the five paths → NOT GOVERNED.
    • Contract surfaces: none touched. There is no Clause-②: yes, no packages/spec path and no governed rule text, so the review is CI plus this seat's read; no second agent was started.
      • The diff adds no prop, export or locale key.
      • Triage's ⛔ on a spec layout key holds: width follows the declared field count.
    • The diff against triage's direction (6093518840):
      • ① Reach: both DialogContents are now flex max-h-[90vh] flex-col, with one min-h-0 flex-1 overflow-y-auto body and the footer outside it.
      • ② Width: more than 8 declared screen fields, or more than 8 shown params, gets sm:max-w-3xl with sm:grid-cols-2.
      • Control: a short screen keeps sm:max-w-md and a single column, and the object-form step keeps its width.
    • Changeset prose, checked sentence by sentence against the diff: "at most 90vh tall", "the fields scroll in their own region between the header and a footer", "more than eight … the wider dialog … two columns from the sm breakpoint up", and "Shorter screens and lists keep their previous width" all match. It is @object-ui/app-shell: patch, with no major.
    • Spot checks:
      • The new pins assert structure, not only classes: the 13 inputs are inside the body, while the heading, Submit and Cancel are outside it and in document order.
      • The dev's reverse run from the committed fix turned the 2 new files red (15 failed), and the restore was proved blob-equal.
      • Reach in Chromium was proven by real mouse.wheel and mouse.click at 1440×900, 1366×768 and 390×844. The record is in the PR body; it was a one-off harness, declared as a deviation and accepted.
    • Declared gap, accepted: check:eager-closure was NOT MEASURED. No module joins the first-load closure (the new imports cn and screenFields come from modules already imported). CI's Bundle Analysis on this head is the reading, and it must be green before the queue.
    • Out of scope: other bare DialogContent call sites are unmeasured. That goes in Acceptance notes, carrier none, and is not filed: a read-only inference.

    Landing: once every check on ca446737ee is green (26 success · 3 skipped · 13 in progress at review), ready + auto-merge through the queue.


    Generated by Claude Code

  7. objectstack-fleet commented on Oct 10, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR objectui#12088 → main 4d0ff233 · domain:ui seat 3, session_01B1gHb9baeX7oioD5sHVm7z, 2026-10-10T10:07Z

    • The merge: through the merge queue. Its one parent is 023f00d4, an ancestor of origin/main.
    • Content check:
      • All five files are blob-identical to the accepted head ca446737ee: FlowRunner.tsx 481cb37d, ActionParamDialog.tsx f409340c, the two pin files and the changeset.
      • max-h-[90vh] is present in both dialogs on 4d0ff233.
      • Control: at 023f00d4 the non-object-form branch reads sm:max-w-md alone.
    • The card: closed completed by the PR's Fixes line. pm:dispatched comes off in the label write after this comment, and domain:, area: and the type label stay.
    • ACCEPT 6096134993.

    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:workflowApprovals and automation — the work that runs without a person driving itbugSomething isn't workingdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions