Skip to content

fix(app-shell): permission grid signals cut columns and pins its Object column and field header - #27909

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-omxklv
Oct 30, 2026
Merged

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

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

维护者速读

  • 改了什么:权限集编辑器的对象矩阵(Setup 页与 Studio Access 的 Objects 页同一套)在列被截断时右边缘出现渐隐提示;Object 列钉在左边(手机上只显示对象名,留出滚动空间);展开字段行后,字段表头(Field / Read / Edit / When)钉在矩阵表头下面;同一对象里两个字段同名(如 Owner)时,把 API 名作为区分文字显示出来。
  • 为什么改:1440 宽时 Bulk 列被截而没有任何提示;手机上横向滚动后看不到每行是哪个对象;展开字段后顶部只剩 C/R/U/D… 的对象表头,压在字段行上,对不上 Read/Edit 列;showcase 的项目和发票对象各有两个都叫「Owner」的字段。
  • 风险与回滚:只改前端样式与布局,权限数据、保存内容不变;回滚即 revert 本 PR。
  • 先看:MatrixScrollPane.tsx(新文件,渐隐提示);PermissionMatrixEditor.tsx 的 STICKY_OBJECT_CELL / FIELD_HEAD_CELL 两个常量及其使用处;FieldsSubTable 里的 sharesLabel。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.gridChrome-27866.test.tsx,预期 9 条全部通过。
  • 需要你做的:无,席位落地。

Fixes #27866

Clause-②: no
Metadata-protocol: none

What changes

All in ui/packages/app-shell/src/views/metadata-admin/ (app-shell is private; it ships inside @object-ui/console):

  • Overflow cue. New MatrixScrollPane.tsx replaces the bare overflow-auto box around the matrix, on the routed page (PermissionTable) and the Studio Objects tab (StudioObjectMatrix). It reads its own box on scroll and on resize (readPaneOverflow) and, while columns are cut on the right, draws an aria-hidden fade over the pane's right edge (perm-matrix-overflow-cue); the fade goes once the last column is in view. It also stamps data-scrolled-x once the pane has scrolled sideways.
  • Pinned Object column. STICKY_OBJECT_CELL pins the Object header and every object row's first cell to the pane's left edge over an opaque background, and draws the column's right edge while data-scrolled-x is set. Row tints (the routed page's hover, the Studio row's active state) are laid on as a background image so the pinned cell keeps them. On a phone the routed page's Object column is w-36 (was w-72) and the (api_name) aside is hidden below sm, so the pinned column takes ~178 px of 390 instead of ~332.
  • Field header pinned under the matrix header. FIELD_HEAD_CELL pins the field sub-table's header cells to top-9, under the matrix header row (now h-9 on the routed page; the Studio row already was), while the sub-table is in view. Field rows scrolled under the matrix header are labelled by their own Field / Read / Edit / When columns, not by the object columns above.
  • Shared labels. When two of an object's offered fields share a label (case-insensitive), each row draws its (api_name) in the foreground, monospace, instead of the muted aside, and carries data-shared-label.

No i18n key, no export from a published package, no metadata change.

Tests

PermissionMatrixEditor.gridChrome-27866.test.tsx (9 tests): readPaneOverflow cases, then on both renderings: the cue shows while the stubbed pane is cut and goes at the end (and for a grid that fits), data-scrolled-x follows; the Object header and row cells are pinned (CONTROL: a box cell is not); the field header cells pin top-9 under an h-9 header row (CONTROL: field rows do not); owner / owner_id both "Owner" draw their API names in the foreground (CONTROL: status keeps the muted aside).

Readings
  • New file at 02dbcde: Test Files 1 passed, Tests 9 passed (9), lock VERDICT command-exit 0.
  • Ablation: PermissionMatrixEditor.tsx restored to origin/main under a trap (markers STICKY_OBJECT_CELL and MatrixScrollPane counted 0), same file: Tests 8 failed, 1 passed (the pure readPaneOverflow case), VERDICT command-exit 1; restored by git checkout HEAD, git diff HEAD empty, blob hash equal to HEAD. Tests import src, so no dist rebuild.
  • Every test file naming PermissionMatrixEditor or MatrixScrollPane (48 files): Test Files 48 passed (48), Tests 340 passed (340), VERDICT command-exit 0.
  • pnpm --filter @object-ui/app-shell run type-check (tsc --noEmit and tsconfig.test.json): VERDICT command-exit 0.

Acceptance notes

Re-driven on stock examples/app-showcase --seed-admin --fresh (admin, Chromium, Setup, permission set member_default) before and after the change, routed page:

  • 1440 px: cut columns are signalled. Before: the pane is 1184 px wide, the grid 1304 px, the Bulk header spans 1372–1560 against a pane edge at 1440, no cue. After: the fade is present at scroll 0 and gone at the end (scrollLeft 120), where the Bulk header's right edge equals the pane's (1440).
  • Phone: the Object column stays visible. Before at 390×844: scrolled to the end, the Object column is gone. After: the Object header and first row cell stay at left 0 (header 0–178) with the pane scrolled 914 px.
  • No two fields carry the same label. On main both rows already showed their API names as a muted aside (Owner (owner), Owner (owner_id) on showcase_project, and the same pair on showcase_invoice); they now draw the API name as the distinguishing text. The duplicate itself is metadata: the showcase authors a text field owner labelled "Owner" beside the platform-injected owner_id, also "Owner". That half is outside this card's file surface (examples/app-showcase, and the injected label under packages/**), named, not done. No two columns share a label.
  • With field rows expanded, each header sits over its column. Before: scrolled into showcase_project's field rows, the only header in view was the object header (C at 584 … Read scope at 1063) while the field Read box sat at 1044. After: the field header pins at top 495, right under the object header (459 + 36), with Read at 1036 over the Read boxes.

Not re-driven live: the Studio Objects tab (pinned by the same tests on that rendering). The fade is drawn over the whole pane's right edge, so on the routed page it also lies over the right margin of the advanced facets and Assigned Users below the grid while columns are cut.


Generated by Claude Code

…ct column and field header

The permission-set grid is wider than its pane at 1440 px and on a phone.
A fade on the pane's right edge now says columns are cut, the Object
column is pinned to the left edge, an expanded object's field header pins
under the matrix header, and two fields sharing a label draw their API
names as the distinguishing text.

Claude-Session: https://claude.ai/code/session_01Utp6CYzrSNZwgsCPhWGAbi
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh

席位核对

ACCEPT · head 02dbcde2c0af2d891eaa1043cf007cdc61eb5bcd · 2026-10-30T03:46Z

  • Shape: draft → main, Fixes #27866. Clause-②: no and Metadata-protocol: none. No new i18n key or export. The changeset is patch on @object-ui/app-shell and @object-ui/console.
  • Change, read (4 files, +355/−20 against origin/main). Only metadata-admin/ is touched: PermissionMatrixEditor.tsx and a new MatrixScrollPane.tsx beside it.
    • While columns are cut, the pane fades its right edge. The fade goes once the last column is in view.
    • The Object column, header and rows, is pinned left on both renderings: the Setup page and Studio's Access Objects tab. On a phone it shows the label alone.
    • The field sub-table header pins under the matrix header (top-9 under h-9).
    • Two offered fields that share a label draw their API names as the distinguishing text.
    • components/src/ui/** and packages/** are untouched.
  • Evidence (report 6514421828): all four symptoms reproduced on main 64e5efde (app-showcase, Setup, member_default). The new suite passes 9/9, and with the implementation reverted 8 go red (the 1 that stays green is a pure function). Related tests: 48 files, 340 passed. app-shell type-check is 0. Derived gates: 34/34 exit 0.
  • Acceptance 2's metadata half is filed as app-showcase: showcase_project and showcase_invoice author an owner field labelled "Owner" beside the platform's owner_id, also "Owner" #27916. The two "Owner" labels are examples/app-showcase metadata: an authored owner text field beside the injected owner_id. That is outside this card's file surface, as its order said. This PR covers the grid's half.
  • Not re-driven live: Studio's Objects tab. The same suite covers it.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure. NOT governed.
  • Landing: non-governed, all green, mergeable_state clean, so the seat lands it with pr_ready and automerge_enable.

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 30, 2026 03:47
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 30, 2026 03:47
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 30, 2026
Merged via the queue into main with commit f8633c7 Oct 30, 2026
56 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/project-thread-omxklv branch October 30, 2026 04:21
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.

Permission-set grid: Bulk column cut at 1440 with no cue, Object column not sticky on phones, two "Owner" labels (#27521 row 17)

1 participant