Skip to content

ui(plugin-grid): in a record drawer, a related list's right-pinned action column (with an inline primary action) covers the Status column at rest #33230

Closed

Description

@os-bob

Found by a downstream app on the published 18.4.0 packages (steedos-labs/os-project-blackcat-crm, the allocation-plan related list of an order).

Symptom

An order opened in a record drawer (from its list, at 1440 / 1280 / 1024 px wide) shows its child related list with a right-pinned actions column. When a row action is promoted inline (a variant: 'primary' custom action, maxInlineActions 1), the pinned column is ~154 px and sits over the last data column (Status) at rest: elementFromPoint at the centre of the Status cell returns the action button, and the Status header is hidden too. Status is revealed only by scrolling the table's scroll box horizontally (753 / 623 px). On the order's full page at 1440 there is no overlap. At 390 px the list renders as cards and the action moves into each card's menu (fine).

Producer (downstream reading, unverified by the PM seat beyond the file reads)

ui/packages/plugin-grid/src/components/RowActionMenu.tsx ~lines 337–343 (inline primary promotion, testid ~529) together with the grid's right-pinned actions column: the pinned column's width grows with the inline button but the scroll box does not reserve it, so a non-overflowing first view is partly covered.

Suggested fix shape (for the lane to judge)

Reserve the pinned column's width in the scroll box (or make the first view overflow-aware), so no data column is covered at rest; or fall back to the menu-only action column when the inline button would cover a data column.

Dedupe words: sticky action column overlaps status · right-pinned action column covers column · related list drawer inline primary.

Activity

  1. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    Contributor

    triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH

    Path: none

    Triage: first touch → domain:ui · p3 · pm:queue · 2026-11-14T07:45Z

    ⛔ Not a claim.

    • Row: in a record drawer, a related list's right-pinned action column (with one inline primary action) sits over the Status column at rest. This is a layout defect; scrolling reveals the column, and no data is wrong: p3.
    • Owner: plugin-grid RowActionMenu.tsx (the pinned column width with an inline action).
  2. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    Contributor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Claim: PM loop round 1 · 2026-11-14T19:57Z
    Session: session_01FEkQ5osPMA12JX9fGcBzR3 (card thread, dev) · seat session_01FEkQ5nWoa1Ze1QzjRTSYXD
    Account: os-project-manager
    Branch: claude/project-thread-vbend6
    Worktree: objectstack-issue-33230
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: ui/packages/plugin-grid/src/ (the right-pinned actions column, RowActionMenu.tsx's inline row button width, the grid scroll box) and its tests; the related-list host in ui/packages/app-shell only if the producer is measured there; root .changeset/. ⛔ No server or packages/spec edit.
    Container & model: S, mode:thread, model: default tier, effort: default
    Clause-②: no
    Metadata-protocol: none
    Responsibility: in a record drawer, a related list whose row has one inline primary action pins an actions column over the last data column at rest | horizontal scroll reveals the column | every user opening a parent record in a drawer whose child list has an inline primary action
    Thread-read: 6874039384
    Premise: downstream reading on published 18.4.0, unverified by the seat; #33215 (PR #33354, d574341a) changed the inline row button since, so the dev reproduces on origin/main first and closes by a pin if it no longer reproduces
    Serial constraints cleared: no other pm:dispatched domain:ui card claims a file in this surface (live label read); no other ui seat holds a Claim: on these files

    Scope: the card's one defect, one PR, Fixes #33230. p3; it was held serial behind #33215, which has merged. The declaration lines start at no / none; the dev measures them on the diff, and the seat amends this claim if they differ. Order: /mnt/project-files/pm-orders/ui/order-33230.md. Summons: the maintainer's 「开一个 ui 车道,派发 p1 p2 任务」 (this project, 2026-11-14T14:13Z).

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 14, 2026
  4. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    Contributor

    domain:ui#1 · os-project-manager · session_01FEkQ5osPMA12JX9fGcBzR3

    os-dev-report

    {
    "issue": 33230,
    "status": "done",
    "branch": "claude/project-thread-vbend6",
    "pr": "#33441",
    "session": "session_01FEkQ5osPMA12JX9fGcBzR3",
    "premise_still_valid": true,
    "summary": "Reproduced on origin/main in a real browser: in the enlarged related list at a drawer's width, the right-pinned Actions column with one inline primary button is 139 px (68 px menu-only), and that width alone tips a table whose data columns fit into one that overflows, so the column covers Status at rest (elementFromPoint at Status's centre answered the inline Allocate button; box 900, table 954, Status 735-815 under the column from 761). The producer is the pinned column's width; the scroll box does reserve the column (scrollWidth includes it, scrolling to the end reveals Status). Fix: ObjectGrid draws inline row buttons only while the table fits its scroll box with them; when it overflows with them, each row's primary action moves to the top of its row menu (planner inline budget 0), and the buttons return once the box is as wide as the table was with them. Readings wait for the table size to hold two frames. No export, prop, authored key, server or spec change.",
    "tests": "New Playwright pin ui/e2e/related-list-pinned-actions-width.spec.ts (real RelatedList enlarged face, Vite-bundled sources, compiled Tailwind, Chromium): drawer 622 px at 1440/1280/1024 windows folded, inline 0, box 622/622, actions left 554 width 68, statusRight 554, Status cell and header hit, Allocate dispatched from the row menu; CONTROL full page 1184 not folded, inline 3, actions width 139, Status hit, inline click dispatches; CONTROL 390 px card layout, Allocate in the card menu; wide drawer (8 columns) folds and Status is reached by scrolling. 6 passed at ee03c81. Ablation at 3afff0c via scripts/ablation-replace.mjs (decide(true) made a no-op): mutation landed (anchor 1 -> 0, blob 53abf59026e5 -> 4dec1046a3e3); drawer1440/1280/1024 red with 'the pinned Actions column covers part of Status at rest' (box 622/654, actions left 483 width 139, statusRight 515), wide case red, both CONTROLs green (4 failed, 2 passed); restored blob == HEAD, git diff HEAD empty. plugin-grid suite 281 files / 2436 tests passed.",
    "gates": "Local: 37 derived families from dispatch-gates --commands plus 4 ui runs outside the derivation, each exit captured before any pipe; dispatch-gates --ran at ee03c81: 37 derived, 37 run, 0 NOT-MEASURED, 0 UNRUN. Record: node scripts/check-adr-0087-registration.mjs --base origin/main :: exit 0 | node scripts/check-adr-0087-registration.mjs --self-test :: exit 0 | node scripts/check-changeset-no-major.mjs --base origin/main :: exit 0 | node scripts/check-closing-keyword-parity.mjs :: exit 0 | node scripts/check-closing-keyword-parity.mjs --self-test :: exit 0 | node scripts/check-comment-mask-corpus.mjs :: exit 0 | node scripts/check-empty-changeset.mjs --base origin/main :: exit 0 | node scripts/check-empty-changeset.mjs --self-test :: exit 0 | node scripts/check-sdui-manifest.mjs :: exit 0 | node scripts/check-sdui-manifest.mjs --self-test :: exit 0 | node scripts/ci/snapshot-next.mjs --self-test :: exit 0 | node scripts/pm/release-rehearsal-clone.mjs --self-test :: exit 0 | node scripts/release-pending-publish.mjs --self-test :: exit 0 | pnpm --filter @objectstack/spec run check:duration-unit-keys :: exit 0 | pnpm check:changeset-gate-self-tests :: exit 0 | pnpm check:closed-ceremony-text :: exit 0 | pnpm check:cross-package-test-inputs :: exit 0 | pnpm check:dispatcher-error-vocabulary :: exit 0 | pnpm check:driver-memory-census :: exit 0 | pnpm check:engine-double-contract :: exit 0 | pnpm check:error-status-conformance :: exit 0 | pnpm check:gitlink-declared :: exit 0 | pnpm check:query-options-erasure :: exit 0 | pnpm check:refd-timer-probe :: exit 0 | pnpm check:skill-identifier-liveness :: exit 0 | pnpm check:test-source-alias :: exit 0 | pnpm check:watch-hint-literal :: exit 0 | pnpm --dir ui --filter @object-ui/plugin-grid run type-check :: exit 0 | pnpm --dir ui run type-check:e2e :: exit 0 | pnpm --dir ui run check:new-line-citations :: exit 0 | pnpm check:undeclared-dep-imports :: exit 0 | pnpm check:tier-file-adoption :: exit 0 | pnpm check:registry-log-declared :: exit 0 | pnpm check:rest-log-spy-declared :: exit 0 | pnpm check:nul-bytes :: exit 0 | pnpm check:type-check-coverage :: exit 0 | pnpm check:published-files :: exit 0 | pnpm check:where-matcher :: exit 0 | pnpm check:type-check-debt :: exit 0 | pnpm --dir ui exec vitest run scripts/ :: exit 0 | pnpm --dir ui exec vitest run packages/plugin-grid/ :: exit 0. First ui scripts run exited 1 on e2e-type-check.test.ts (the pin's page entry named @object-ui packages in a source string); fixed in ee03c81, whole suite reran exit 0 (171 passed, 2 skipped) and the gates that read the spec reran. CI check runs on #33441: in_progress at report time (not waited for, per os-dev.md).",
    "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
    "mcp_calls": "3 — mcp__github__issue_read x3 (card, comments, claim read-back); no MCP write",
    "api_writes": "2 — POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, run 43641810403, read-back identical 9823 bytes, no labels, no assignees) and this os-dev-report comment via post-stamped. Plus git push x3 to claude/project-thread-vbend6 (not REST).",
    "line_budget": "589 changed lines (+585 / -4) over 5 files, under the 3000 human-merge threshold",
    "files_changed": [
    ".changeset/33230-related-list-inline-action-fold.md",
    "ui/e2e/related-list-pinned-actions-width.spec.ts",
    "ui/packages/plugin-grid/src/ObjectGrid.tsx",
    "ui/packages/plugin-grid/src/objectGridActionsColumn.tsx",
    "ui/packages/plugin-grid/src/objectGridInlineActionFold.ts"
    ],
    "deviations": [
    "pr_create carries no assignees: the order says no assignees, while os-dev.md rule 2 says pr_create carries the claim's Account; the order's explicit line was followed.",
    "Builds and suites ran outside scripts/pm/os-verify-lock.sh: this card thread is the only agent in its container.",
    "The live Console drawer could not show an enlarged related list (the showcase's authored page has no enlarge control), so the drawer width was measured live (720 px pane, 622 px content) and the defect was reproduced and pinned in the browser harness."
    ],
    "open_questions": [
    {
    "question": "A table that overflows the drawer even menu-only (many columns) still has the folded pinned column over the data at the box's right edge at rest, as the full list page does today. Should the line 'no data column covered at rest' also hold there?",
    "status": "needs_decision",
    "options": [
    "A Keep as is: the fold covers every table the inline button alone tipped over; a table that overflows anyway scrolls sideways under a 68 px pinned menu column, the standard sideways-scroll behaviour (this PR).",
    "B Un-pin the Actions column whenever the table overflows, so the last column is visible at rest but the row menu scrolls out of reach until the user scrolls.",
    "C Reserve a gutter of the pinned column's width after the last data column, so scrolling to the end shows everything (already true) and at rest the covered column is whichever reaches the edge (no change at rest)."
    ],
    "recommendation": "A. Business need: the card's measured case (drawer, inline button tipping the table) is fixed; no measured report covers the menu-only overflow case, which the list page has always had. Long-term: pinning the action column is the established list contract; B trades action reach for one column. AI-error axis: neutral, no metadata involved. Startup focus: B or C would be a new layout policy with no pull. Leave as is unless a real report arrives."
    }
    ],
    "security_findings": "none",
    "out_of_scope_findings": [
    "carrier: none · the menu-only overflow regime (on the live Console list page at a 1440 px window, End Date sits under the right-pinned Actions column at rest, origin/main behaviour) is the design question in open_questions and the PR's Acceptance notes, not a filed defect"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    Contributor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Seat review: PR #33441 ACCEPT on head ee03c81e (2026-11-14T21:37Z), open question ruled A (existing sideways-scroll contract). Base synced (K = 21); it lands after the rerun is green.

  6. objectstack-fleet commented on Nov 14, 2026

    @objectstack-fleet
    Contributor

    domain:ui#1 · os-project-manager · session_01FEkQ5nWoa1Ze1QzjRTSYXD

    Landed · 2026-11-14T22:41Z

    reading value
    PR #33441 MERGED as f068cde8 on main (closes this card via Fixes #33230)
    contract record not owed (Clause-② no)

    State: pm:dispatched removed, assignee cleared; card closed by the merge. The open question (menu-only overflow) was ruled A in the ACCEPT, the existing sideways-scroll contract. #33317 (same plugin-grid files) is now free to dispatch.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    domain:uiDomain lane — seat card indexed by label:pm:seatpriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions