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:
parent
bb62bf1aa9
commit
26b0b0d173
2 changed files with 294 additions and 175 deletions
74
frontend/packages/swarm-ui/src/pages/AgentsPage.css
Normal file
74
frontend/packages/swarm-ui/src/pages/AgentsPage.css
Normal 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;
|
||||
}
|
||||
Loading…
Reference in a new issue