Skip to content

fix(plugin-detail): a record page's body table wider than the details column pins its first column and offers ⤢ as "All columns" - #29982

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-pivz06
Nov 3, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-pivz06

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Yibo Wang · project thread

Fixes #29945

Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:记录页正文子表(详情列里的关联列表)列太多、超出详情列宽度时,现在会明确提示:首列(记录名)横向滚动时固定不动;表头右上角的放大按钮从只有图标变成带文字的「全部列」按钮;右侧阴影(18.3 已有)照旧随滚动位置出现和消失。表格放得下时以上提示都不出现。
  • 为什么改:hotclm 的合同子表有 7、8 列,在 1440 宽的页面上只露出 4、5 列,读者看不出右边还有列(滚动条悬停才出现,右侧阴影很淡)。表格仍留在详情列里,不跨到右侧栏:ADR-0085 的按角色分栏布局决定了正文表的位置,改栅格会动所有记录页的列布局,归 ADR-0085 §5 / epic epic: record page v2 — one default open mode per object (drawer by default, page by declaration; modal / split / popover retired as metadata); the drawer and the page are one page at two widths; related records open in place #26676,不在本卡范围。
  • 风险与回滚:只在「正文子表且确实溢出」时改变外观;data-table 表头标签多了一个 title(所有表格都有,悬停显示完整列名),滚动容器多一个 data-table-scroll-box 标记属性。新增一个 i18n 键(10 个语言)。不加 spec 键、不改布局;回滚即还原本 PR。
  • 先看:ui/packages/plugin-detail/src/RelatedList.tsx 中 bodyTableOverflows 的读数 effect 和放大按钮的两种形态;ui/packages/components/src/renderers/complex/data-table.tsx 的两处属性;测试 RelatedList.bodyTable-27055.test.tsx 新增的 objectstack#29945 用例组。
  • 两分钟验证:在仓根运行 pnpm --dir ui exec vitest run packages/plugin-detail/src/__tests__/RelatedList.bodyTable-27055.test.tsx,预期 15 个测试全部通过(8 列:有阴影、首列 sticky、放大按钮带文字;滚到末尾阴影消失;3 列放得下:三者皆无)。
  • 需要你做的:无,席位落地。

What changes

The seat's ruling for this card keeps the record page v3 grid (ADR-0085's role-based layout puts body tables in the details column) and makes the overflow obvious instead. A body table (bodyTable in RelatedList, a related list in RecordBodyTablesContext) now reads whether it is wider than its column, and while it is:

Cue Before (18.3.0) After
Right-edge shadow while columns remain to the right drawn by data-table (objectui#12708); clears at the end unchanged, reused
First (identity) column scrolls away pinned: the table's existing frozenColumns: 1, set only while the table overflows
⤢ enlarge control icon-only ghost button outline button with a visible label, detail.relatedCardAllColumns ("All columns" / 「全部列」); same enlargeRelated call, same enlarged tab
Header label the ellipsis would cut no full text title with the whole label (every data-table, see below)

A body table that fits shows none of these: no pinned column, the icon-only ⤢ (aria-label "Enlarge"), and data-table draws no shadow.

How overflow is read. RelatedList wraps the table in a host div and, in a layout effect, finds the table's scroll box by a new data-table-scroll-box marker and reads scrollWidth - clientWidth > 1, re-read by a ResizeObserver on the box and on its table (rows arriving, columns sizing themselves). If the table mounts after the list (a deferred renderer) a MutationObserver waits for the box, then disconnects. The effect is keyed on primitives only (bodyTableDrawn, isMobile; ui/AGENTS.md commandment 10). Under 768 px the body table is the card gallery and reads false. The PM's mechanism assumption holds: overflow is detectable from the scroll container with a ResizeObserver, and jsdom has no layout, so the tests stub the widths.

No new scroll-shadow or sticky utility. The shadow is data-table's own (from custom/use-horizontal-overflow), the pin is data-table's frozenColumns. Neither was changed.

@object-ui/components, two attributes on data-table. (1) the header label span carries title={col.header}. This reaches every data-table, not only body tables (a non-body-table header case is pinned, below). (2) the scroll box carries data-table-scroll-box="" for a host that reads its overflow. In a table's auto layout a header cell is never narrower than its nowrap label, so (1) is the hover fallback for the ellipsis; the card's "Busines…" reads as the box edge cutting the column, which the pinned first column, the shadow and the labelled ⤢ now announce.

Tests

New top-level describe in the existing body-table harness, RelatedList.bodyTable-27055.test.tsx (the widths stubbed on HTMLElement.prototype for the element carrying data-table-scroll-box: 120 px per header cell inside a 680 px column; restored in afterAll):

Ablation. On fix commit 384e15f8, through scripts/ablation-replace.mjs: the overflow read setBodyTableOverflows(box.scrollWidth - box.clientWidth > 1) replaced by setBodyTableOverflows(false /* ABLATED-29945 */): anchor x1 → x0, blob fc68c4aefa7e → 6e7dc9971b75; 2 tests red ("eight columns in the details column…" and "scrolled to the end…"), 13 green (the CONTROL among them). Restored: blob == HEAD fc68c4aefa7e, git diff HEAD empty. The test imports ../RelatedList from source, so no build sat between the mutation and the run.

Acceptance notes

  • The right-edge shadow already shipped in 18.3.0. npm pack @object-ui/components@18.3.0 carries data-table-scroll-shadow-right in dist/index.js, so the card's "no visible cue" was measured against a page that had the shadow (a from-foreground/10 gradient 24 px wide) and a scrollbar that stays transparent until hover. This PR leaves the shared shadow as it is and adds the pinned column and the labelled ⤢; whether the shared shadow itself should be stronger is a data-table-wide design call, not taken here.
  • Screenshot at 1440×900: NOT-MEASURED. Reason: a showcase or hotclm-like boot needs the full workspace build plus the Console build, beyond this card's size; the hotclm evidence paths named on the card are not in this project's shared folder. The behaviour is pinned in jsdom with stubbed widths.
  • Left side. Once scrolled, the pinned first column's seam (border-r-2 + shadow, data-table's frozen-column styling) is the left-edge cue; no separate left shadow was added.
  • No new spec key; Metadata-protocol: none. No change to which column a body table sits in.
  • In-flight overlap re-checked at PR time: full-text search of open PRs for plugin-detail and data-table names none touching RelatedList.tsx or data-table.tsx (hits: the Version Packages PR and unrelated plugin-auth / spec / lint PRs).

Verification

All on head d361bd80 (shared box; lock VERDICT lines quoted).

Build, type-check, vitest
  • npx turbo run build --filter='@object-ui/plugin-detail...' --concurrency=2: VERDICT command-exit 0 (52 tasks, 6m31s)
  • npx turbo run build --filter=@object-ui/components --filter=@object-ui/i18n --filter=@object-ui/plugin-detail --concurrency=2: VERDICT command-exit 0 (52 tasks, 47 cached)
  • pnpm --filter @object-ui/plugin-detail type-check, … @object-ui/components type-check, … @object-ui/i18n type-check (each tsc --noEmit && tsc -p tsconfig.test.json): VERDICT command-exit 0 ×3
  • pnpm --dir ui exec vitest run --maxWorkers=2 packages/plugin-detail/: VERDICT command-exit 0 · Test Files 369 passed | 1 skipped (370) · Tests 3253 passed | 18 skipped (3271)
  • pnpm --dir ui exec vitest run --maxWorkers=2 packages/components/: VERDICT command-exit 0 · Test Files 476 passed | 1 skipped (477) · Tests 4548 passed | 24 skipped (4572)
  • pnpm --dir ui exec vitest run --maxWorkers=2 packages/i18n/: VERDICT command-exit 0 · Test Files 95 passed (95) · Tests 1443 passed | 13 skipped (1456)
  • pnpm --dir ui exec vitest run packages/plugin-detail/src/__tests__/RelatedList.bodyTable-27055.test.tsx: 15 passed (15)
  • npx eslint on the changed files from each package dir: 0 errors (warnings only, pre-existing no-explicit-any class)
Derived gates (`dispatch-gates --commands`, 35 lines, then `--ran`)
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/pm/release-rehearsal-clone.mjs --self-test :: exit 0
node scripts/release-pending-publish.mjs --self-test :: exit 0
pnpm --dir ui exec vitest run scripts/ :: 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:gitlink-declared :: exit 0
pnpm check:nul-bytes :: exit 0
pnpm check:published-files :: exit 0
pnpm check:query-options-erasure :: exit 0
pnpm check:refd-timer-probe :: exit 0
pnpm check:registry-log-declared :: exit 0
pnpm check:rest-log-spy-declared :: exit 0
pnpm check:skill-identifier-liveness :: exit 0
pnpm check:test-source-alias :: exit 0
pnpm check:tier-file-adoption :: exit 0
pnpm check:type-check-coverage :: exit 0
pnpm check:type-check-debt :: exit 0
pnpm check:undeclared-dep-imports :: exit 0
pnpm check:watch-hint-literal :: exit 0
pnpm check:where-matcher :: exit 0
pnpm check:changeset-fixed :: exit 0   (roster under .changeset, outside the derived 35)

dispatch-gates --ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN, exit 0 ("a DERIVED zero — all 35 recorded an exit code and none of them is 3"). CI check-runs: read by the seat.


Generated by Claude Code

…than its column

A body table that overflows the details column pins its first column,
keeps the table's own right-edge shadow, and offers the enlarge control
with a visible label; a table that fits shows none of these cues.

Claude-Session: https://claude.ai/code/session_01WGufziRW9G6UKkSyGRbh7x
Co-authored-by: Claude <noreply@anthropic.com>
…or the body-table overflow cues

Claude-Session: https://claude.ai/code/session_01WGufziRW9G6UKkSyGRbh7x
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Nov 3, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#1 · os-support-ai · session_01WGufzjDyeFwq6AuFu3vwTd

维护者速读(席位终稿)

  • 改了什么:记录页正文子表列太多、超出详情列宽度时,首列(记录名)在横向滚动时固定不动,表头的放大按钮从只有图标变成带文字的「全部列」按钮。右侧阴影是 18.3 已有的,照旧随滚动出现和消失。表格放得下时这些提示都不出现。所有数据表的表头都多了悬停显示完整列名。
  • 为什么改:hotclm 合同子表 7、8 列,在 1440 宽页面上只露出 4、5 列,读者看不出右边还有列。
  • 风险与回滚:低。只在「正文子表且确实溢出」时改外观;表格仍在详情列里,不改页面栅格(席位裁决,见派发令)。新增一个 10 语言的 i18n 键,不加 spec 键。回滚即还原本 PR。
  • 先看:RelatedList.tsx 的 bodyTableOverflows 读数 effect 和放大按钮两种形态;data-table.tsx 的两处属性。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/plugin-detail/src/__tests__/RelatedList.bodyTable-27055.test.tsx,15 个用例全过。
  • 需要你做的:无,非受管面,CI 全绿后席位落地。
  • 席位意见:ACCEPT。复用表格已有的 frozenColumns 和右侧阴影,没有另造工具;放得下的对照组也有测试。

席位核对 · ACCEPT · head d361bd80f60ea966f30ec42f72789ae5d4964153 · 2026-11-03T22:45Z

  1. Shape: draft, base main, attribution block then Fixes #29945. One changeset (@object-ui/plugin-detail, @object-ui/components, @object-ui/i18n patch) with Clause-②: no / Metadata-protocol: none; 14 files, +235/−6. check-governed-merges --pr 29982: NOT governed (0 of 14 paths), 241 lines ≤ 3000. No contract face; this seat's read is the review of record.
  2. Premise, measured: at origin/main a body table had no sticky column and an icon-only ⤢; the right-edge shadow (objectui#12708) already ships in @object-ui/components 18.3.0, faint, and is reused unchanged. The diff reads overflow off the DataTable's own scroll box (data-table-scroll-box, scrollWidth − clientWidth > 1, ResizeObserver on box and table, MutationObserver until a late-mounted box appears) and, only while it overflows, passes the table's existing frozenColumns: 1 and renders ⤢ as a labelled outline button calling the same enlargeRelated. Placement unchanged, per the seat ruling in the order.
  3. Gates: dev's local union at d361bd80: the test file 15/15; plugin-detail, components and i18n suites and type-checks green; dispatch-gates --commands 35/35 exit 0 plus check:changeset-fixed, --ran reconciled. Ablation (overflow read forced false): the 2 overflow cases red, 13 green incl. CONTROL, blob restored. Screenshot NOT-MEASURED (needs a full Console build); jsdom widths stubbed on the scroll box, stated in the report. CI on this head was in progress at this reading; landing waits for every check green or expected-skip.
  4. Surface amended (Claim 6616106390): data-table.tsx gets two attributes only (the scroll-box marker and title={col.header} on the header label). The title reaches every DataTable; the seat asked for a non-body-table pin and it is there (the plain related-list case in the console record page v3: frameless detail sections, one merged timeline (discussion + activity + field changes), compact related cards, header 1 primary + 2 secondary + ⋯ — the synthesized default page, drawn from the object's roles; the dead BuildPageOptions hints go #27055 describe asserts th span[title="Quantity"]). Accepted. The PR's attribution line links the card thread rather than the seat thread, as Console sign-in page cannot reach the mobile hand-off: a redirect to the auth API lands on 页面不存在 #29971's did. Accepted.
  5. Out of scope: re-gridding the record page so body tables span the side column (card option a) stays with ADR-0085 §5 / epic epic: record page v2 — one default open mode per object (drawer by default, page by declaration; modal / split / popover retired as metadata); the drawer and the page are one page at two widths; related records open in place #26676. No packages/spec/**. mcp_calls: 3 reads, no write tool.
  6. Landing: ordinary queue. When every check on this head is green or expected-skip: relay pr_ready + automerge_enable, follow to MERGED, record the landing on Record page v3 body tables sit in the narrow details column, so a seven-column child list hides its last columns behind a horizontal scroll at 1440 px #29945.

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

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Record page v3 body tables sit in the narrow details column, so a seven-column child list hides its last columns behind a horizontal scroll at 1440 px

1 participant