From 7a371573fd6c5f8c2a49ad7031aef099abce2ae2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=8C=85=E5=91=A8=E6=B6=9B?= Date: Tue, 4 Aug 2026 00:21:33 -0700 Subject: [PATCH] fix(app-shell): cap the permission-set capability chip wall so the object matrix stays reachable (#3332) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The system-capabilities section in PermissionMatrixEditPage rendered the CapabilityMultiSelectField chip wall unbounded. It is a non-shrinking sibling of the flex-1 object-permission matrix inside an overflow-hidden column, so a large capability registry (44+ navigation capabilities, 20+ chip rows) squeezed the matrix scroll container to ~9px while the page itself had no scrollbar — the object CRUD grid became unreachable. Wrap the picker in a max-h-[30vh] overscroll-contained scroll area: the capability area keeps at most a viewport share and scrolls internally, and the matrix keeps the remaining height. Per objectui#2600 B1 the picker itself stays inline (no extra click) when grants exist. Covers both entry points (Setup metadata route via builtinComponents and StudioDesignSurface), which render the same editor. Co-Authored-By: Claude Fable 5 --- .../PermissionMatrixEditor.basics.test.tsx | 15 ++++++++++ .../metadata-admin/PermissionMatrixEditor.tsx | 29 +++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.basics.test.tsx b/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.basics.test.tsx index 5876b93668..78873e3996 100644 --- a/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.basics.test.tsx +++ b/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.basics.test.tsx @@ -96,4 +96,19 @@ describe('PermissionMatrixEditPage — B1 first-screen collapse (objectui#2600)' expect(screen.getByTestId('cap-picker')).toBeInTheDocument(); expect(screen.queryByRole('button', { name: /Add capability/i })).toBeNull(); }); + + // objectui#3332 — a large capability chip wall (44+ grants → 20+ rows) is a + // non-shrinking sibling of the flex-1 object matrix; unbounded it squeezed + // the matrix to ~9px with no page scrollbar. The picker must sit inside a + // height-capped, internally-scrolling container so the matrix keeps the rest + // of the viewport. + it('caps the capability area with its own scroll so the matrix stays reachable (objectui#3332)', async () => { + await renderSet({ + systemPermissions: Array.from({ length: 44 }, (_, i) => `navigation.item_${i}`), + }); + const wrap = screen.getByTestId('capability-scroll'); + expect(wrap).toContainElement(screen.getByTestId('cap-picker')); + expect(wrap.className).toContain('overflow-y-auto'); + expect(wrap.className).toMatch(/max-h-/); + }); }); diff --git a/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx b/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx index c929a15fc3..6f2c24b8a1 100644 --- a/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx +++ b/packages/app-shell/src/views/metadata-admin/PermissionMatrixEditor.tsx @@ -775,15 +775,26 @@ export function PermissionMatrixEditPage({ type, name, packageId, onDraftSaved,

{t('perm.field.systemCapabilitiesHelp')}

- - setDraft((p) => ({ ...p, systemPermissions: parseCapabilityNames(v) })) - } - field={{ name: 'system_permissions' } as any} - dataSource={adapter as any} - readonly={!writable} - /> + {/* objectui#3332 — the capability chip wall grows with the live + sys_capability registry (44+ nav capabilities → 20+ rows). It is + a non-shrinking sibling of the flex-1 matrix, so unbounded it + squeezes the object list to ~0px with no page scrollbar. Cap it + to a viewport share and scroll internally; the matrix keeps the + remaining height (per #2600 B1 the picker itself stays inline). */} +
+ + setDraft((p) => ({ ...p, systemPermissions: parseCapabilityNames(v) })) + } + field={{ name: 'system_permissions' } as any} + dataSource={adapter as any} + readonly={!writable} + /> +
)}