Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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-/);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -775,15 +775,26 @@ export function PermissionMatrixEditPage({ type, name, packageId, onDraftSaved,
<p className="text-xs text-muted-foreground mt-0.5 mb-2">
{t('perm.field.systemCapabilitiesHelp')}
</p>
<CapabilityMultiSelectField
value={JSON.stringify(draft.systemPermissions ?? [])}
onChange={(v: unknown) =>
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). */}
<div
data-testid="capability-scroll"
className="max-h-[30vh] overflow-y-auto overscroll-contain"
>
<CapabilityMultiSelectField
value={JSON.stringify(draft.systemPermissions ?? [])}
onChange={(v: unknown) =>
setDraft((p) => ({ ...p, systemPermissions: parseCapabilityNames(v) }))
}
field={{ name: 'system_permissions' } as any}
dataSource={adapter as any}
readonly={!writable}
/>
</div>
</div>
)}

Expand Down
Loading