From bf289aa1b119715c1f28476c97fd191566543c31 Mon Sep 17 00:00:00 2001 From: hsiegeln <37154749+hsiegeln@users.noreply.github.com> Date: Thu, 16 Apr 2026 13:27:53 +0200 Subject: [PATCH] docs: add runtime compact view design spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../2026-04-16-runtime-compact-view-design.md | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-16-runtime-compact-view-design.md diff --git a/docs/superpowers/specs/2026-04-16-runtime-compact-view-design.md b/docs/superpowers/specs/2026-04-16-runtime-compact-view-design.md new file mode 100644 index 00000000..5c616c79 --- /dev/null +++ b/docs/superpowers/specs/2026-04-16-runtime-compact-view-design.md @@ -0,0 +1,91 @@ +# Runtime Dashboard — Compact View + +## Summary + +Add a compact/collapsed view mode to the runtime dashboard (AgentHealth page). In compact mode, each application is rendered as a small status card showing app name, live agent count, and last heartbeat, with health-state coloring (tinted background + tinted border + thick left accent border). Individual cards can be expanded inline to reveal the full agent instance table. A global toggle switches between compact and expanded views. + +## Decisions + +| Question | Decision | +|----------|----------| +| Default view | Compact — all apps start collapsed | +| Expand behavior | Inline — card expands in place, pushes others down | +| Grid layout | Auto-fill responsive (`repeat(auto-fill, minmax(220px, 1fr))`) | +| Toggle location | Inside stat strip area (icon toggle, no new toolbar row) | +| Health coloring | Same logic as existing `appHealth()` — worst agent state wins | +| Card styling | Tinted background (8% health color) + tinted border (25%) + 3px left accent border | + +## View Mode State + +- `viewMode: 'compact' | 'expanded'` — persisted to `localStorage` key `cameleer:runtime:viewMode`, default `'compact'`. +- `expandedApps: Set` — tracks individually expanded app IDs. Ephemeral (not persisted). +- When `viewMode === 'compact'`: apps in `expandedApps` show the full GroupCard table. All others show compact cards. +- When `viewMode === 'expanded'`: all apps show the full GroupCard table (current behavior). `expandedApps` is ignored. +- Collapse all / expand all: sets `viewMode` and clears `expandedApps`. + +## View Toggle + +- Two-button icon toggle rendered in the `.statStrip` area after the last StatCard. +- Uses `Button` from `@cameleer/design-system` with `variant="ghost"`. Active button styled with `var(--running)` background. +- Icons: `LayoutGrid` (compact) / `List` (expanded) from `lucide-react`. +- `.statStrip` grid changes from `repeat(5, 1fr)` to `repeat(5, 1fr) auto` to accommodate the toggle. + +## Compact Card (CompactAppCard) + +Inline component in `AgentHealth.tsx` (page-specific, not reusable). + +**Props:** `group: AppGroup`, `onExpand: () => void`. + +**Layout:** +- Container: `var(--bg-raised)` with health-color tint via CSS custom property `--card-accent`. + - `background: color-mix(in srgb, var(--card-accent) 8%, var(--bg-raised))` + - `border: 1px solid color-mix(in srgb, var(--card-accent) 25%, transparent)` + - `border-left: 3px solid var(--card-accent)` + - `border-radius: var(--radius-md)` + - Cursor pointer, entire card clickable. +- **Row 1:** App name (font-weight 700, `var(--text-primary)`) left. `ChevronRight` icon (`var(--text-muted)`) right. +- **Row 2:** `"{liveCount}/{total} live"` in health color (font-weight 600) left. Last heartbeat right — computed as `timeAgo(max(instances.map(i => i.lastHeartbeat)))` (most recent across all instances in the group). Color: `var(--text-muted)` when healthy, health color when stale/dead. +- **Hover:** tint increases to 12%. + +**Health color mapping** (reuses existing `appHealth()` function): +- `.compactCardSuccess` → `--card-accent: var(--success)` +- `.compactCardWarning` → `--card-accent: var(--warning)` +- `.compactCardError` → `--card-accent: var(--error)` + +## Expanded Card in Compact Mode + +- Renders existing `GroupCard` + `DataTable` unchanged. +- GroupCard header gets a `ChevronDown` icon button to collapse back. +- Expanded card gets `grid-column: span 2` in the compact grid for adequate table width (roughly matches current half-page GroupCard width). +- **Animation (single card toggle):** CSS transition on wrapper div with `overflow: hidden`. Expand: compact fades out (opacity 0, ~100ms), expanded fades in + grows (opacity 1, max-height transition, ~200ms ease-out). Collapse: reverse. Collapse-all / expand-all toggle is instant (no animation). + +## Grid Layout + +- `viewMode === 'expanded'`: existing `.groupGrid` (2-column `1fr 1fr`, unchanged). +- `viewMode === 'compact'`: new `.compactGrid` class: + ```css + .compactGrid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); + gap: 10px; + margin-bottom: 20px; + } + ``` + +## Files Changed + +| File | Change | +|------|--------| +| `ui/src/pages/AgentHealth/AgentHealth.tsx` | `viewMode`/`expandedApps` state, localStorage init, `CompactAppCard` component, view toggle in stat strip, conditional grid rendering | +| `ui/src/pages/AgentHealth/AgentHealth.module.css` | `.compactGrid`, `.compactCard`, `.compactCardSuccess/Warning/Error`, `.compactCardHeader`, `.compactCardMeta`, `.viewToggle`, `.viewToggleActive`, animation classes, `.statStrip` column adjustment | +| `.claude/rules/ui.md` | Add compact view mention under Runtime section | + +No new files. No new design system components. No API changes. Feature is entirely contained in the AgentHealth page and its CSS module. + +## Style Guide Compliance + +- All colors via `@cameleer/design-system` CSS variables (`var(--success)`, `var(--warning)`, `var(--error)`, `var(--bg-raised)`, `var(--text-primary)`, `var(--text-muted)`, `var(--running)`, `var(--radius-md)`, `var(--border-subtle)`). +- No hardcoded hex values. +- Shared CSS modules imported where applicable. +- Design system components (`Button`, `GroupCard`, `DataTable`, `StatusDot`, `Badge`, `MonoText`) used throughout. +- `lucide-react` for icons (consistent with rest of UI).