Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui: the permissions box lists every permission instead of a narrow scroll area

The checkbox list was capped at 12em and scrolled, and the box shrinks the
list to its widest label, so the scrollbar sat in the middle of the popover
with the lower permissions hidden. The permissions are a short fixed list:
MultiselectFilterOptions takes scrollable={false} and the permissions box
uses it. Filter lists that can grow long keep the scroll area.
This commit is contained in:
iris 2026-11-06 00:22:14 +01:00 • committed by mara
commit 33c230665b
4 changed files with 17 additions and 2 deletions

View file

@ -690,7 +690,8 @@ a badge reading the default set, none, or a count. A swarm
grant is the agent's whole set, so it follows the agent to whichever hive runs
it. Selecting the badge opens a box under it with one checkbox per permission the controller
knows (`GET /api/permissions`), ticked as the grant stands, or on the default
set when the swarm sets none.
set when the swarm sets none. The box lists every permission at once, without a
scroll area.
Each tick saves at once, as a `PUT /api/agents/{agent}/permissions` of the ticked boxes. A
`PUT` replaces the stored list whole, so an unticked box revokes that

View file

@ -224,6 +224,7 @@ export function AgentPermissions({
filter={{ values: ticked, negate: false }}
onToggle={(v) => void toggle(v)}
disabled={busy}
scrollable={false}
/>
</div>
) : (

View file

@ -10,6 +10,10 @@
max-height: 12em;
overflow-y: auto;
}
.ui-multiselect-filter-options-all {
max-height: none;
overflow-y: visible;
}
.ui-multiselect-filter-checkbox {
display: flex;
align-items: center;

View file

@ -31,15 +31,24 @@ export function MultiselectFilterOptions({
filter,
onToggle,
disabled = false,
scrollable = true,
}: {
options: string[];
filter: MultiselectFilterState;
onToggle: (value: string) => void;
/** Greys the boxes out, e.g. while a change is being saved. */
disabled?: boolean;
/** A long list scrolls inside its box. Off: every option shows, for a short
* fixed list that a scroll area would only hide part of. */
scrollable?: boolean;
}) {
return (
<div class="ui-multiselect-filter-options">
<div
class={
"ui-multiselect-filter-options" +
(scrollable ? "" : " ui-multiselect-filter-options-all")
}
>
{options.map((v) => (
<label key={v} class="ui-multiselect-filter-checkbox">
<input