swarm-ui: extract Card/MultiselectFilter/SplitView per component-first design
Mara: "result looks like the shape i am looking for, but the code does not. you did not follow component first principle" - the card's clickable/selectable mechanics, the card-view filter trigger+popover, and the list+detail split layout were all one-off page-local JSX in AgentsPage.tsx instead of docs/web-ui/design-guide.md's "Component-first design" primitives. Three new ui/ components, each with a same-day /components demo section per that doc's own rule: - ui/card/Card.tsx - the role=button/keyboard-activation/selected mechanics AgentCard now wraps agent-specific content around, instead of owning them itself. - ui/multiselect-filter/MultiselectFilter.tsx - the checkbox-list trigger+popover control. This was also a straight duplicate of Table's own inline popover content once AgentsPage's filter toolbar needed the identical thing; Table now renders the same MultiselectFilterOptions piece too (keeping its own th-anchored trigger and fixed+portal positioning, which are genuinely table-specific), not a second copy. - ui/split-view/SplitView.tsx - the list+detail flex-wrap layout, no opinion on what's inside either pane. AgentsPage.tsx's own CSS shrinks to just the agent-specific content inside these primitives (card line/message layout, detail-panel field grid, the name-search input) - the container/positioning rules moved to each component's own colocated CSS. No behavior change for any other Table caller (HivesPage, IssueReportPage, the components demo's own Table samples) - the popover's visual output is identical, just sourced from the shared component instead of inline JSX. Verified: typecheck/build clean, real screenshots of both AgentsPage (pixel-identical to before) and the three new /components sections, plus a live click confirming MultiselectFilter's popover opens correctly on the demo page too.
This commit is contained in:
parent
60d7e8ce84
commit
7003560569
11 changed files with 646 additions and 400 deletions
14
frontend/packages/swarm-ui/src/ui/split-view/SplitView.css
Normal file
14
frontend/packages/swarm-ui/src/ui/split-view/SplitView.css
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
.ui-split-view {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1em;
|
||||
align-items: flex-start;
|
||||
}
|
||||
.ui-split-view-primary {
|
||||
flex: 2 1 480px;
|
||||
min-width: 0;
|
||||
}
|
||||
.ui-split-view-secondary {
|
||||
flex: 1 1 320px;
|
||||
min-width: 0;
|
||||
}
|
||||
33
frontend/packages/swarm-ui/src/ui/split-view/SplitView.tsx
Normal file
33
frontend/packages/swarm-ui/src/ui/split-view/SplitView.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
// <SplitView> — a primary/secondary pane laid out side by side, wrapping
|
||||
// to stacked on a narrow viewport. Extracted out of `AgentsPage`'s own
|
||||
// list+detail row (design-guide's "Component-first design": a page had
|
||||
// built this inline for its own list/detail split, `AgentsPage`'s
|
||||
// `Panel`s reaching for it is the first real use, per the doc's "build
|
||||
// the primitive before or alongside the first real page that needs it").
|
||||
//
|
||||
// `flex-wrap`, not a `@media` breakpoint — content-driven stacking, same
|
||||
// approach the shell's own nav row already uses (`shell/Shell.css`)
|
||||
// rather than a second, independent magic-number breakpoint. No opinion
|
||||
// on what's inside either pane (a `Panel`, anything else) — same "own
|
||||
// the mechanics, not the content" split as `Card`.
|
||||
import type { ComponentChildren } from "preact";
|
||||
import "./SplitView.css";
|
||||
|
||||
export function SplitView({
|
||||
primary,
|
||||
secondary,
|
||||
}: {
|
||||
/** The wider pane — a list, a table, whatever the page's main content
|
||||
* is. `flex: 2` against `secondary`'s `flex: 1`. */
|
||||
primary: ComponentChildren;
|
||||
/** The narrower pane — a detail view, a summary, anything that reads
|
||||
* as "more about the thing selected in `primary`." */
|
||||
secondary: ComponentChildren;
|
||||
}) {
|
||||
return (
|
||||
<div class="ui-split-view">
|
||||
<div class="ui-split-view-primary">{primary}</div>
|
||||
<div class="ui-split-view-secondary">{secondary}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue