Recharts — Skill
Name: recharts
Purpose: Build responsive, readable charts with Recharts using correct data mapping and composition.
Use this skill whenever creating charts with Recharts.
Applies when: Using LineChart, BarChart, AreaChart, PieChart, ResponsiveContainer.
Do not use when: Charts are not built with Recharts.
Rules
- •Always responsive: Wrap charts in
ResponsiveContainerand ensure a fixed height parent. - •Explicit data model: Normalize data and use stable
dataKeyvalues. - •Pick the simplest chart: Use
LineChartfor trends,BarChartfor comparisons,AreaChartfor cumulative/volume,PieChartfor part-to-whole. - •Interactivity: Add
Tooltip; addLegendwhen multiple series exist. - •Performance: Disable animation for large/static dashboards and reduce point count.
Workflow
- •Define the data shape and stable keys.
- •Choose the simplest chart that answers the question.
- •Wrap in
ResponsiveContainerwith a height. - •Add axes, tooltip, and legend as needed.
- •Disable animation or aggregate data for large sets.
Checklists
Implementation checklist
- • Chart is wrapped in
ResponsiveContainer - • X/Y axes are present when needed
- • Tooltip shows correct units
- •
dataKeymatches field names
Review checklist
- • Animations disabled for large datasets
- • Colors are accessible
Minimal examples
Line chart (trend)
tsx
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
} from "recharts";
export function SalesChart({
data,
}: {
data: Array<{ month: string; sales: number }>;
}) {
return (
<div style={{ height: 320 }}>
<ResponsiveContainer width="100%" height="100%">
<LineChart
data={data}
margin={{ top: 8, right: 16, bottom: 8, left: 8 }}
>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="month" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="sales" dot={false} />
</LineChart>
</ResponsiveContainer>
</div>
);
}
Custom tooltip
tsx
type TooltipProps = {
active?: boolean;
label?: string;
payload?: Array<{ name?: string; value?: number | string }>;
};
export function CustomTooltip({ active, label, payload }: TooltipProps) {
if (!active || !payload?.length) return null;
return (
<div className="rounded-md border bg-white p-2 text-sm shadow">
<div className="font-medium">{label}</div>
<ul className="mt-1 space-y-0.5">
{payload.map((p, i) => (
<li key={i}>
{p.name}: {p.value}
</li>
))}
</ul>
</div>
);
}
Common mistakes / pitfalls
- •Missing
ResponsiveContaineror fixed-height parent - •Mismatched
dataKeyvalues - •Over-animating large dashboards
- •Rendering too many points without aggregation