432 lines
15 KiB
Markdown
432 lines
15 KiB
Markdown
|
|
# Documentation Updates Implementation Plan
|
||
|
|
|
||
|
|
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
|
|
||
|
|
**Goal:** Update COMPONENT_GUIDE.md and Inventory page with entries and demos for all new components: KpiStrip, SplitPane, EntityList, LogViewer, StatusText, and Card title extension.
|
||
|
|
|
||
|
|
**Architecture:** COMPONENT_GUIDE.md gets new decision tree entries and component index rows. Inventory page gets DemoCard sections with realistic sample data for each new component.
|
||
|
|
|
||
|
|
**Tech Stack:** React, TypeScript, CSS Modules
|
||
|
|
|
||
|
|
**Spec:** `docs/superpowers/specs/2026-03-24-mock-deviations-design.md` (Documentation Updates section)
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 1: Update COMPONENT_GUIDE.md
|
||
|
|
|
||
|
|
**File:** `COMPONENT_GUIDE.md`
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **1a.** In the `"I need to show status"` decision tree (line ~34), add StatusText entry after StatusDot:
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
- Inline colored status value → **StatusText** (success, warning, error, running, muted — with optional bold)
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1b.** In the `"I need to display data"` decision tree (line ~51), add three entries after the EventFeed line:
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
- Row of summary KPIs → **KpiStrip** (horizontal strip with colored borders, trends, sparklines)
|
||
|
|
- Scrollable log output → **LogViewer** (timestamped, severity-colored monospace entries)
|
||
|
|
- Searchable, selectable entity list → **EntityList** (search header, selection highlighting, pairs with SplitPane)
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1c.** In the `"I need to organize content"` decision tree (line ~62), add SplitPane entry after DetailPanel and update the Card entry:
|
||
|
|
|
||
|
|
After the `- Side panel inspector → **DetailPanel**` line, add:
|
||
|
|
```markdown
|
||
|
|
- Master/detail split layout → **SplitPane** (list on left, detail on right, configurable ratio)
|
||
|
|
```
|
||
|
|
|
||
|
|
Update the existing Card line from:
|
||
|
|
```markdown
|
||
|
|
- Grouped content box → **Card** (with optional accent)
|
||
|
|
```
|
||
|
|
to:
|
||
|
|
```markdown
|
||
|
|
- Grouped content box → **Card** (with optional accent and title)
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1d.** In the `"I need to display text"` decision tree (line ~72), add StatusText cross-reference:
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
- Colored inline status text → **StatusText** (semantic color + optional bold, see also "I need to show status")
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1e.** Add a new composition pattern after the existing "KPI dashboard" pattern (line ~113):
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
### Master/detail management pattern
|
||
|
|
```
|
||
|
|
SplitPane + EntityList for CRUD list/detail screens (users, groups, roles)
|
||
|
|
EntityList provides: search header, add button, selectable list
|
||
|
|
SplitPane provides: responsive two-column layout with empty state
|
||
|
|
```
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1f.** Add five new rows to the Component Index table (maintaining alphabetical order):
|
||
|
|
|
||
|
|
After the `EventFeed` row:
|
||
|
|
```markdown
|
||
|
|
| EntityList | composite | Searchable, selectable entity list with add button. Pair with SplitPane for CRUD management screens |
|
||
|
|
```
|
||
|
|
|
||
|
|
After the `KeyboardHint` row:
|
||
|
|
```markdown
|
||
|
|
| KpiStrip | composite | Horizontal row of KPI cards with colored left border, trend, subtitle, optional sparkline |
|
||
|
|
```
|
||
|
|
|
||
|
|
After the `LineChart` row:
|
||
|
|
```markdown
|
||
|
|
| LogViewer | composite | Scrollable log output with timestamped, severity-colored monospace entries |
|
||
|
|
```
|
||
|
|
|
||
|
|
After the `Sparkline` row:
|
||
|
|
```markdown
|
||
|
|
| SplitPane | composite | Two-column master/detail layout with configurable ratio and empty state |
|
||
|
|
| StatusText | primitive | Inline colored status span (success, warning, error, running, muted) with optional bold |
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **1g.** Update the existing `Card` row in the Component Index from:
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
| Card | primitive | Content container with optional accent border |
|
||
|
|
```
|
||
|
|
|
||
|
|
to:
|
||
|
|
|
||
|
|
```markdown
|
||
|
|
| Card | primitive | Content container with optional accent border and title header |
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 2: Add StatusText demo to PrimitivesSection
|
||
|
|
|
||
|
|
**File:** `src/pages/Inventory/sections/PrimitivesSection.tsx`
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **2a.** Add `StatusText` to the import from `'../../../design-system/primitives'` (insert alphabetically after `StatCard`):
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
StatusText,
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **2b.** Add a new DemoCard after the StatusDot demo (after line ~560, before the Tag demo). Insert this block:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{/* 29. StatusText */}
|
||
|
|
<DemoCard
|
||
|
|
id="statustext"
|
||
|
|
title="StatusText"
|
||
|
|
description="Inline coloured text for status values — five semantic variants with optional bold."
|
||
|
|
>
|
||
|
|
<div className={styles.demoAreaColumn} style={{ width: '100%' }}>
|
||
|
|
<div className={styles.demoAreaRow}>
|
||
|
|
<StatusText variant="success">99.8% uptime</StatusText>
|
||
|
|
<StatusText variant="warning">SLA at risk</StatusText>
|
||
|
|
<StatusText variant="error">BREACH</StatusText>
|
||
|
|
<StatusText variant="running">Processing</StatusText>
|
||
|
|
<StatusText variant="muted">N/A</StatusText>
|
||
|
|
</div>
|
||
|
|
<div className={styles.demoAreaRow}>
|
||
|
|
<StatusText variant="success" bold>99.8% uptime</StatusText>
|
||
|
|
<StatusText variant="warning" bold>SLA at risk</StatusText>
|
||
|
|
<StatusText variant="error" bold>BREACH</StatusText>
|
||
|
|
<StatusText variant="running" bold>Processing</StatusText>
|
||
|
|
<StatusText variant="muted" bold>N/A</StatusText>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</DemoCard>
|
||
|
|
```
|
||
|
|
|
||
|
|
Note: Renumber subsequent demos (Tag becomes 30, Textarea becomes 31, Toggle becomes 32, Tooltip becomes 33).
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 3: Update Card demo in PrimitivesSection
|
||
|
|
|
||
|
|
**File:** `src/pages/Inventory/sections/PrimitivesSection.tsx`
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **3a.** Update the Card DemoCard description from:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
description="Surface container with optional left-border accent colour."
|
||
|
|
```
|
||
|
|
|
||
|
|
to:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
description="Surface container with optional left-border accent colour and title header."
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **3b.** Add a title prop example to the Card demo. After the existing `Card accent="error"` line (~212), add:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
<Card title="Throughput (msg/s)">
|
||
|
|
<div style={{ padding: '8px 12px', fontSize: 13 }}>Card with title header and separator</div>
|
||
|
|
</Card>
|
||
|
|
<Card accent="amber" title="Error Rate">
|
||
|
|
<div style={{ padding: '8px 12px', fontSize: 13 }}>Title + accent combined</div>
|
||
|
|
</Card>
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 4: Add composite demos to CompositesSection
|
||
|
|
|
||
|
|
**File:** `src/pages/Inventory/sections/CompositesSection.tsx`
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **4a.** Add new imports. Add `KpiStrip`, `SplitPane`, `EntityList`, `LogViewer` to the import from `'../../../design-system/composites'` (insert alphabetically):
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
EntityList,
|
||
|
|
KpiStrip,
|
||
|
|
LogViewer,
|
||
|
|
SplitPane,
|
||
|
|
```
|
||
|
|
|
||
|
|
Also add `Badge` and `Avatar` to the import from `'../../../design-system/primitives'` (needed for EntityList demo renderItem):
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { Avatar, Badge, Button } from '../../../design-system/primitives'
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4b.** Add sample data constants after the existing sample data section (before the `CompositesSection` function). Add:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
// ── Sample data for new composites ───────────────────────────────────────────
|
||
|
|
|
||
|
|
const KPI_ITEMS = [
|
||
|
|
{
|
||
|
|
label: 'Exchanges',
|
||
|
|
value: '12,847',
|
||
|
|
trend: { label: '↑ +8.2%', variant: 'success' as const },
|
||
|
|
subtitle: 'Last 24h',
|
||
|
|
sparkline: [40, 55, 48, 62, 70, 65, 78],
|
||
|
|
borderColor: 'var(--amber)',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
label: 'Error Rate',
|
||
|
|
value: '0.34%',
|
||
|
|
trend: { label: '↑ +0.12pp', variant: 'error' as const },
|
||
|
|
subtitle: 'Above threshold',
|
||
|
|
sparkline: [10, 12, 11, 15, 18, 22, 19],
|
||
|
|
borderColor: 'var(--error)',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
label: 'Avg Latency',
|
||
|
|
value: '142ms',
|
||
|
|
trend: { label: '↓ -12ms', variant: 'success' as const },
|
||
|
|
subtitle: 'P95: 380ms',
|
||
|
|
borderColor: 'var(--success)',
|
||
|
|
},
|
||
|
|
{
|
||
|
|
label: 'Active Routes',
|
||
|
|
value: '37',
|
||
|
|
trend: { label: '±0', variant: 'muted' as const },
|
||
|
|
subtitle: '3 paused',
|
||
|
|
borderColor: 'var(--running)',
|
||
|
|
},
|
||
|
|
]
|
||
|
|
|
||
|
|
const ENTITY_LIST_ITEMS = [
|
||
|
|
{ id: '1', name: 'Alice Johnson', email: 'alice@example.com', role: 'Admin' },
|
||
|
|
{ id: '2', name: 'Bob Chen', email: 'bob@example.com', role: 'Editor' },
|
||
|
|
{ id: '3', name: 'Carol Smith', email: 'carol@example.com', role: 'Viewer' },
|
||
|
|
{ id: '4', name: 'David Park', email: 'david@example.com', role: 'Editor' },
|
||
|
|
{ id: '5', name: 'Eva Martinez', email: 'eva@example.com', role: 'Admin' },
|
||
|
|
]
|
||
|
|
|
||
|
|
const LOG_ENTRIES = [
|
||
|
|
{ timestamp: '2026-03-24T10:00:01Z', level: 'info' as const, message: 'Route timer-aggregator started successfully' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:03Z', level: 'debug' as const, message: 'Polling endpoint https://api.internal/health — 200 OK' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:15Z', level: 'warn' as const, message: 'Retry queue depth at 847 — approaching threshold (1000)' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:22Z', level: 'error' as const, message: 'Exchange failed: Connection refused to jdbc:postgresql://db-primary:5432/orders' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:23Z', level: 'info' as const, message: 'Failover activated — routing to db-secondary' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:30Z', level: 'info' as const, message: 'Exchange completed in 142ms via fallback route' },
|
||
|
|
{ timestamp: '2026-03-24T10:00:45Z', level: 'debug' as const, message: 'Metrics flush: 328 data points written to InfluxDB' },
|
||
|
|
{ timestamp: '2026-03-24T10:01:00Z', level: 'warn' as const, message: 'Memory usage at 78% — GC scheduled' },
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4c.** Add state variables inside the `CompositesSection` function for EntityList demo:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
// EntityList state
|
||
|
|
const [selectedEntityId, setSelectedEntityId] = useState<string | undefined>('1')
|
||
|
|
const [entitySearch, setEntitySearch] = useState('')
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4d.** Add KpiStrip demo after the existing GroupCard demo. Insert a new DemoCard:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{/* KpiStrip */}
|
||
|
|
<DemoCard
|
||
|
|
id="kpistrip"
|
||
|
|
title="KpiStrip"
|
||
|
|
description="Horizontal row of KPI cards with coloured left border, trend indicator, subtitle, and optional sparkline."
|
||
|
|
>
|
||
|
|
<div style={{ width: '100%' }}>
|
||
|
|
<KpiStrip items={KPI_ITEMS} />
|
||
|
|
</div>
|
||
|
|
</DemoCard>
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4e.** Add SplitPane demo:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{/* SplitPane */}
|
||
|
|
<DemoCard
|
||
|
|
id="splitpane"
|
||
|
|
title="SplitPane"
|
||
|
|
description="Two-column master/detail layout with configurable ratio and empty-state placeholder."
|
||
|
|
>
|
||
|
|
<div style={{ width: '100%', height: 200 }}>
|
||
|
|
<SplitPane
|
||
|
|
list={
|
||
|
|
<div style={{ padding: 16, fontSize: 13 }}>
|
||
|
|
<div style={{ fontWeight: 600, marginBottom: 8 }}>Items</div>
|
||
|
|
<div>Item A</div>
|
||
|
|
<div>Item B</div>
|
||
|
|
<div>Item C</div>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
detail={
|
||
|
|
<div style={{ padding: 16, fontSize: 13 }}>
|
||
|
|
<div style={{ fontWeight: 600, marginBottom: 8 }}>Detail View</div>
|
||
|
|
<div>Select an item on the left to see its details here.</div>
|
||
|
|
</div>
|
||
|
|
}
|
||
|
|
ratio="1:2"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</DemoCard>
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4f.** Add EntityList demo:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{/* EntityList */}
|
||
|
|
<DemoCard
|
||
|
|
id="entitylist"
|
||
|
|
title="EntityList"
|
||
|
|
description="Searchable, selectable entity list with add button — designed to pair with SplitPane."
|
||
|
|
>
|
||
|
|
<div style={{ width: '100%', height: 260 }}>
|
||
|
|
<EntityList
|
||
|
|
items={ENTITY_LIST_ITEMS.filter(u =>
|
||
|
|
u.name.toLowerCase().includes(entitySearch.toLowerCase())
|
||
|
|
)}
|
||
|
|
renderItem={(item, isSelected) => (
|
||
|
|
<div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
|
||
|
|
<Avatar name={item.name} size="sm" />
|
||
|
|
<div>
|
||
|
|
<div style={{ fontSize: 13, fontWeight: isSelected ? 600 : 400 }}>{item.name}</div>
|
||
|
|
<div style={{ fontSize: 11, color: 'var(--text-muted)' }}>{item.email}</div>
|
||
|
|
</div>
|
||
|
|
<Badge label={item.role} style={{ marginLeft: 'auto' }} />
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
getItemId={(item) => item.id}
|
||
|
|
selectedId={selectedEntityId}
|
||
|
|
onSelect={setSelectedEntityId}
|
||
|
|
searchPlaceholder="Search users..."
|
||
|
|
onSearch={setEntitySearch}
|
||
|
|
addLabel="+ Add user"
|
||
|
|
onAdd={() => {}}
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
</DemoCard>
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4g.** Add LogViewer demo:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{/* LogViewer */}
|
||
|
|
<DemoCard
|
||
|
|
id="logviewer"
|
||
|
|
title="LogViewer"
|
||
|
|
description="Scrollable log output with timestamped, severity-coloured monospace entries and auto-scroll."
|
||
|
|
>
|
||
|
|
<div style={{ width: '100%' }}>
|
||
|
|
<LogViewer entries={LOG_ENTRIES} maxHeight={240} />
|
||
|
|
</div>
|
||
|
|
</DemoCard>
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **4h.** Verify all four new DemoCards are placed in alphabetical order among existing demos — EntityList after EventFeed, KpiStrip after GroupCard, LogViewer after LoginForm, SplitPane after ShortcutsBar. Adjust comment numbering accordingly.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 5: Update Inventory nav
|
||
|
|
|
||
|
|
**File:** `src/pages/Inventory/Inventory.tsx`
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **5a.** Add `StatusText` to the Primitives nav components array (insert alphabetically after `StatusDot`):
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
{ label: 'StatusText', href: '#statustext' },
|
||
|
|
```
|
||
|
|
|
||
|
|
- [ ] **5b.** Add four entries to the Composites nav components array (insert alphabetically):
|
||
|
|
|
||
|
|
After `EventFeed`:
|
||
|
|
```tsx
|
||
|
|
{ label: 'EntityList', href: '#entitylist' },
|
||
|
|
```
|
||
|
|
|
||
|
|
After `GroupCard`:
|
||
|
|
```tsx
|
||
|
|
{ label: 'KpiStrip', href: '#kpistrip' },
|
||
|
|
```
|
||
|
|
|
||
|
|
After `LoginForm`:
|
||
|
|
```tsx
|
||
|
|
{ label: 'LogViewer', href: '#logviewer' },
|
||
|
|
```
|
||
|
|
|
||
|
|
After `ShortcutsBar`:
|
||
|
|
```tsx
|
||
|
|
{ label: 'SplitPane', href: '#splitpane' },
|
||
|
|
```
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Task 6: Commit all documentation
|
||
|
|
|
||
|
|
### Steps
|
||
|
|
|
||
|
|
- [ ] **6a.** Run `npx vitest run src/pages/Inventory` to verify Inventory page has no import/type errors (if tests exist for it).
|
||
|
|
- [ ] **6b.** Stage changed files:
|
||
|
|
- `COMPONENT_GUIDE.md`
|
||
|
|
- `src/pages/Inventory/Inventory.tsx`
|
||
|
|
- `src/pages/Inventory/sections/PrimitivesSection.tsx`
|
||
|
|
- `src/pages/Inventory/sections/CompositesSection.tsx`
|
||
|
|
- [ ] **6c.** Commit with message: `docs: add COMPONENT_GUIDE entries and Inventory demos for KpiStrip, SplitPane, EntityList, LogViewer, StatusText, Card title`
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
## Dependency Notes
|
||
|
|
|
||
|
|
- **Tasks 1-5 are independent** and can be worked in any order.
|
||
|
|
- **Task 6 depends on Tasks 1-5** being complete.
|
||
|
|
- **All tasks depend on the components already existing** — StatusText, Card title extension, KpiStrip, SplitPane, EntityList, and LogViewer must be built and exported from their barrel files before the Inventory demos will compile.
|
||
|
|
|
||
|
|
## Files Modified
|
||
|
|
|
||
|
|
| File | Change |
|
||
|
|
|------|--------|
|
||
|
|
| `COMPONENT_GUIDE.md` | Decision tree entries + component index rows |
|
||
|
|
| `src/pages/Inventory/Inventory.tsx` | 5 new nav entries (1 primitive + 4 composites) |
|
||
|
|
| `src/pages/Inventory/sections/PrimitivesSection.tsx` | StatusText demo + Card title demo update |
|
||
|
|
| `src/pages/Inventory/sections/CompositesSection.tsx` | KpiStrip, SplitPane, EntityList, LogViewer demos with sample data |
|