From b168d7c867d7d67065e7153e585c4ab52394a431 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Tue, 24 Mar 2026 11:54:52 +0100 Subject: [PATCH] docs: add EntityList, docs updates, and inventory to spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-03-24-mock-deviations-design.md | 95 ++++++++++++++++++- 1 file changed, 93 insertions(+), 2 deletions(-) diff --git a/docs/superpowers/specs/2026-03-24-mock-deviations-design.md b/docs/superpowers/specs/2026-03-24-mock-deviations-design.md index d8d2cae..0e3dad4 100644 --- a/docs/superpowers/specs/2026-03-24-mock-deviations-design.md +++ b/docs/superpowers/specs/2026-03-24-mock-deviations-design.md @@ -84,6 +84,74 @@ interface SplitPaneProps { --- +## 2b. EntityList — New Composite + +**Problem:** The left-side list panels in UsersTab, GroupsTab, and RolesTab all build the same frame: a search input + "Add" button header, a scrollable list of items (avatar + text + badges), and selection highlighting. Each tab re-implements this frame with ~50 lines of identical structure. + +**Solution:** New composite `EntityList`. + +```tsx +interface EntityListProps { + items: T[] + renderItem: (item: T, isSelected: boolean) => ReactNode + getItemId: (item: T) => string + selectedId?: string + onSelect?: (id: string) => void + searchPlaceholder?: string // Default: "Search..." + onSearch?: (query: string) => void + addLabel?: string // e.g. "+ Add user" — omit to hide button + onAdd?: () => void + emptyMessage?: string // Default: "No items found" + className?: string +} +``` + +**Layout:** +- Header row: `Input` (search, with icon) on the left, `Button variant="secondary" size="sm"` (add) on the right. Header hidden when both `onSearch` and `onAdd` are omitted. +- Scrollable list below header, `var(--bg-surface)` background +- Each item: clickable row with `var(--bg-hover)` on hover, `var(--amber-bg)` + left amber border when selected +- Items rendered via `renderItem` — the component provides the clickable row wrapper, the caller provides the content +- `role="listbox"` on the list, `role="option"` on each item for accessibility +- Empty state: centered `emptyMessage` text when `items` is empty + +**Typical item content (provided by caller via `renderItem`):** +- Avatar + name + subtitle + badge tags — but this is not prescribed by EntityList. The component is agnostic about item content. + +**Combined usage with SplitPane:** +```tsx + ( + <> + +
+
{user.name}
+
{user.email}
+
{user.roles.map(r => )}
+
+ + )} + getItemId={(u) => u.id} + selectedId={selectedId} + onSelect={setSelectedId} + searchPlaceholder="Search users..." + onSearch={setSearchQuery} + addLabel="+ Add user" + onAdd={() => setAddDialogOpen(true)} + /> + } + detail={selectedUser ? : null} +/> +``` + +**File location:** `src/design-system/composites/EntityList/` + +**Pages to refactor:** UsersTab.tsx, GroupsTab.tsx, RolesTab.tsx — replace custom list rendering with ``. Combined with SplitPane, each tab reduces from ~200 lines to ~50 lines of domain-specific render logic. + +--- + ## 3. Refactor AgentHealth Instance Table to DataTable **Problem:** AgentHealth builds instance tables using raw HTML `` elements instead of the existing `DataTable` composite. @@ -189,7 +257,7 @@ interface CardProps { 1. **KpiStrip** — highest impact, 3 pages, ~320 lines eliminated 2. **StatusText** — smallest scope, quick win, unblocks cleaner page code 3. **Card title** — small change to existing component, unblocks Routes cleanup -4. **SplitPane** — 3 admin tabs, clean pattern +4. **SplitPane + EntityList** — 3 admin tabs, clean pattern. Build together since EntityList is the natural content for SplitPane's list slot. 5. **LogViewer** — 1 page but important for real app 6. **AgentHealth DataTable refactor** — pure page cleanup, no DS changes @@ -201,4 +269,27 @@ All new components tested with Vitest + React Testing Library, co-located test f New components added to respective barrel exports: - `src/design-system/primitives/index.ts` — StatusText -- `src/design-system/composites/index.ts` — KpiStrip, SplitPane, LogViewer +- `src/design-system/composites/index.ts` — KpiStrip, SplitPane, EntityList, LogViewer + +## Documentation Updates + +### COMPONENT_GUIDE.md + +Add entries for each new component to the appropriate decision trees: + +- **Data Display section:** Add KpiStrip — "Use KpiStrip for a row of summary metrics at the top of a page (exchanges, error rate, latency, etc.)" +- **Data Display section:** Add LogViewer — "Use LogViewer for scrollable log output with timestamped, severity-colored entries" +- **Layout section:** Add SplitPane — "Use SplitPane for master/detail layouts: selectable list on the left, detail view on the right" +- **Data Display section:** Add EntityList — "Use EntityList for searchable, selectable lists of entities (users, groups, roles, etc.). Combine with SplitPane for CRUD management screens." +- **Text & Labels section:** Add StatusText — "Use StatusText for inline colored status values (success rates, SLA status, trend indicators). Use StatusDot for colored dot indicators." +- **Card section:** Document new `title` prop — "Pass `title` to Card for a titled content container (e.g., chart cards). Title renders as an uppercase header with separator." + +### Inventory Page + +Add demos for each new component to `src/pages/Inventory/sections/`: + +- **CompositesSection.tsx:** Add KpiStrip, SplitPane, EntityList, LogViewer demos with realistic sample data +- **PrimitivesSection.tsx:** Add StatusText demo showing all variants +- **Card demo:** Update existing Card demo to show the `title` prop variant + +Each demo follows the existing DemoCard pattern with `id` anchors, and nav entries are added to `Inventory.tsx`.