# 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)