Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui/agents: per-agent card view + detail panel, split from the roster table

Replaces AgentsPage's Table-rendered roster with one AgentCard per
agent: name/status/wanted on the first line, the free-form status
message on the second (mara, scoping #4257: "main view: name, status,
message, wanted" / "message as second line" / "more like card per
agent").

Everything the old table's other columns carried (hive, matrix
link-account, config-PR link, destroy) moves into a detail panel that
opens on card click, reusing the existing Dialog modal rather than a
new docked/slideover primitive - the shared hive-side-panel drawer is a
shadow-DOM custom element swarm-ui's esbuild config can't consume yet
(same gap Dialog.tsx's own comment already flags for hive-dialog).

WantedMenu gains a showDestroy flag: the card's own menu keeps the
three everyday states, destroy gets its own button in the detail panel
instead of a fourth dropdown entry next to states someone reaches for
often.

Known regression, flagged for follow-up rather than silently dropped:
the old table's per-column sort/filter has no replacement in this view
yet.

Backend list/detail endpoint split (also requested in #4257) is
deliberately left for a follow-up PR - it's an orthogonal optimization,
not required for this interaction to work correctly against the
existing single /api/agents/status response.
This commit is contained in:
iris 2026-09-11 21:37:17 +02:00
commit 26b0b0d173
2 changed files with 294 additions and 175 deletions

View file

@ -0,0 +1,74 @@
/* <AgentCard> list — a vertical stack of per-agent cards replacing the
old table body (mara: "more like card per agent"). Full-width rows,
not a grid: the second line (the agent's free-form status message)
reads better wrapping the card's own width than squeezed into a fixed
grid cell. */
.ui-agent-card-list {
display: flex;
flex-direction: column;
gap: 0.5em;
}
.ui-agent-card-list-empty {
color: var(--muted);
text-align: center;
padding: 1.25em 0.75em;
}
.ui-agent-card {
display: flex;
flex-direction: column;
gap: 0.35em;
padding: 0.75em 1em;
border: 1px solid var(--border);
border-radius: 0.5em;
background: var(--bg-elev);
cursor: pointer;
}
.ui-agent-card:hover,
.ui-agent-card:focus-visible {
border-color: var(--purple);
outline: none;
}
.ui-agent-card-line1 {
display: flex;
align-items: center;
gap: 0.6em;
}
.ui-agent-card-name {
font-weight: 600;
}
/* Pushes the wanted-state control to the row's trailing edge regardless
of how wide the status badge next to it ends up. */
.ui-agent-card-wanted {
display: inline-flex;
align-items: center;
gap: 0.4em;
margin-left: auto;
}
.ui-agent-card-message {
color: var(--muted);
white-space: normal;
word-break: break-word;
}
/* Detail panel (`Dialog` body) — the fields `AgentCard`'s main view
doesn't show. */
.ui-agent-detail-name {
margin: 0 0 0.75em;
}
.ui-agent-detail-fields {
display: grid;
grid-template-columns: auto 1fr;
gap: 0.4em 1em;
margin: 0 0 1em;
}
.ui-agent-detail-fields dt {
color: var(--muted);
}
.ui-agent-detail-fields dd {
margin: 0;
}
.ui-agent-detail-actions {
display: flex;
align-items: center;
gap: 0.75em;
}