Watch
0
0
Fork
You've already forked hyperhive
0

swarm-ui/agents: split the page, extract FilterableView per mara's follow-up

Three more asks from the same review thread:

- "agentspage is now giant and deserves a split" - AgentsPage.tsx was
  1047 lines. Split into AgentTypes.ts (AgentRow and friends),
  WantedMenu.tsx, AgentCard.tsx (+ its own CSS), leaving AgentsPage.tsx
  as state/actions/columns/the render tree - 649 lines, and every piece
  it composes is now independently readable.

- "what about the component that represents filtered data ... that the
  card view and table can both use?" - extracted FilterableView
  (ui/filterable-view/): takes columns/rows/rowKey/storageKey/view/
  renderCard, builds its filter bar from *every* filterable column (not
  a hand-picked subset - the old AgentFilterBar only showed 4 of the
  agent columns' 6 filterable fields, an accidental gap the table's own
  popovers didn't have), and renders either the card list or Table.
  AgentsPage now just tells it which view to show; the view toggle
  itself stays page-side since it's Panel-header chrome, not filtering.
  Disclosed side effect: card view's filter bar now also covers
  message/config-PR (text filters), matching table view exactly instead
  of a narrower subset.

- CSS audit: AgentsPage.css now holds only what's genuinely page-specific
  (the view toggle, the detail-panel field grid) - everything else moved
  to its owning component's own colocated CSS.

FilterableView gets a /components demo (view toggle + filter bar + both
render modes, same day per the design guide). Verified: AgentsPage
still renders the same (real screenshot), and the demo's own table
toggle produces a real Table with the same rows.
This commit is contained in:
iris 2026-09-11 22:30:38 +02:00
commit 601068f1eb
9 changed files with 591 additions and 491 deletions

View file

@ -1,18 +1,7 @@
/* <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. Each card's own clickable/selected/border styling is
`Card`'s (`ui/card/`) — this file only lays out agent-specific
content inside one. */
.ui-agent-card-list {
display: flex;
flex-direction: column;
gap: 0.5em;
}
/* Shared by both views (`Table` has its own `emptyMessage` rendering,
but the card view has nothing equivalent — this covers both, and
`AgentsPage` only mounts it when `rows` is loaded and empty). */
/* Detail panel's "select an agent" empty state. `FilterableView`
(`ui/filterable-view/`) has its own equivalent for its two empty
cases — colocated there instead of shared with this one, since the
two components have no other reason to depend on each other's CSS. */
.ui-agents-empty {
color: var(--muted);
text-align: center;
@ -47,27 +36,6 @@
.ui-agents-view-toggle button:not(.active):hover {
color: var(--fg);
}
.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 body — its own `Panel`, title supplied by the panel's
`title` prop (the agent's name), not repeated in here. */
@ -88,25 +56,3 @@
align-items: center;
gap: 0.75em;
}
/* Card view's filter toolbar — `Table`'s per-column popovers, minus the
table to hang them off of. Each `MultiselectFilter` (`ui/
multiselect-filter/`) owns its own trigger/popover styling; this file
only lays out the row they sit in plus the name-search input, which
has no shared-component equivalent (a plain text input). */
.ui-agents-filter-bar {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 0.5em;
margin-bottom: 0.75em;
}
.ui-agents-filter-search {
background: var(--bg);
color: var(--fg);
border: 1px solid var(--border);
border-radius: 4px;
padding: 0.35em 0.6em;
font: inherit;
font-size: 0.9em;
}