diff --git a/docs/superpowers/specs/2026-04-12-recharts-migration-design.md b/docs/superpowers/specs/2026-04-12-recharts-migration-design.md new file mode 100644 index 0000000..050a10c --- /dev/null +++ b/docs/superpowers/specs/2026-04-12-recharts-migration-design.md @@ -0,0 +1,121 @@ +# Recharts Migration Design + +## Goal + +Replace the design system's hand-rolled SVG chart components (LineChart, AreaChart, BarChart) with Recharts-based implementations. The current custom charts have responsiveness issues (preserveAspectRatio distorting text), limited tooltip/axis formatting, and growing maintenance burden. + +## Architecture + +Add Recharts as a DS dependency. Replace the three custom chart components and `_chart-utils.ts` with a single `ThemedChart` wrapper component. Consumers compose Recharts elements (``, ``, ``, etc.) as children inside ``. The DS re-exports Recharts components so consumers don't need to add Recharts as a separate dependency. + +Sparkline stays hand-rolled SVG (no axes, no tooltips — Recharts is overkill). + +### What gets removed + +- `composites/LineChart/` directory (LineChart.tsx, LineChart.module.css) +- `composites/AreaChart/` directory (AreaChart.tsx, AreaChart.module.css) +- `composites/BarChart/` directory (BarChart.tsx, BarChart.module.css) +- `composites/_chart-utils.ts` +- `ChartSeries` and `DataPoint` type exports + +### What gets added + +- `composites/ThemedChart/ThemedChart.tsx` — wrapper component +- `composites/ThemedChart/ChartTooltip.tsx` — internal themed tooltip +- `composites/ThemedChart/ThemedChart.module.css` +- Recharts re-exports from the DS barrel + +### What stays unchanged + +- `utils/rechartsTheme.ts` (now also used internally by ThemedChart) +- `CHART_COLORS` +- `primitives/Sparkline/` + +## Data Format + +Consumers use Recharts-native flat data format instead of the current `ChartSeries[]`: + +```tsx +// Before (custom) +const series = [ + { label: 'CPU %', data: pts.map(p => ({ x: new Date(p.time), y: p.value * 100 })) } +] + + +// After (Recharts-native) +const data = pts.map(p => ({ time: p.time, cpu: p.value * 100 })) + + + +``` + +This is a breaking change. The migration cost is bounded — only `AgentInstance.tsx` in the server repo uses these components. + +## ThemedChart API + +```tsx +interface ThemedChartProps { + data: Record[] + height?: number // default 200 + xDataKey?: string // default "time" + xType?: 'number' | 'category' // default "category" + xTickFormatter?: (value: any) => string + yTickFormatter?: (value: any) => string + yLabel?: string + children: React.ReactNode // Recharts elements + className?: string +} +``` + +ThemedChart renders internally: +- `ResponsiveContainer` (width 100%, height from prop) +- `ComposedChart` (supports mixing Line + Bar + Area in one chart) +- `CartesianGrid` with `rechartsTheme.cartesianGrid` +- `XAxis` with `rechartsTheme.xAxis` + formatter +- `YAxis` with `rechartsTheme.yAxis` + formatter + label +- `Tooltip` with custom `ChartTooltip` component + +## Tooltip + +ThemedChart provides a custom `ChartTooltip` component (internal, not exported) that: +- Shows the x-value formatted as date/time in a header row (mono font, subtle border separator) +- Shows each series with colored dot + label + formatted value +- Uses DS tokens for styling (surface bg, border, shadow, mono font) + +Consumers can override by passing their own `` as a child. Recharts uses the last Tooltip it finds, so a consumer-provided one replaces the default. + +## DS Re-exports + +Selected Recharts components re-exported so consumers don't need `recharts` in their own package.json: + +```tsx +export { ThemedChart } from './ThemedChart/ThemedChart' +export { + Line, Area, Bar, ReferenceLine, ReferenceArea, + Legend, Brush, ComposedChart, +} from 'recharts' +``` + +More can be added on demand. + +## Consumer Migration — Server UI + +`AgentInstance.tsx` has 6 charts to migrate: + +| Chart | Before | After | +|-------|--------|-------| +| CPU Usage | `` | `` | +| Memory (Heap) | `` | `` | +| Throughput | `` | `` | +| Error Rate | `` | `` | +| Thread Count | `` | `` | +| GC Pauses | `` | `` | + +Data prep changes from building `ChartSeries[]` arrays to flat objects with named keys. + +## Not in Scope + +- Sparkline migration (no responsiveness issues, no axes/tooltips) +- SaaS UI (no chart component usage) +- Dashboard tab (already uses Recharts directly with `rechartsTheme`) +- New chart types (treemap, radar, etc. — consumers compose these directly)