dist/plugins/web-dataviz-recharts/skills/web-dataviz-recharts/SKILL.md
Recharts composable chart components - LineChart, BarChart, AreaChart, PieChart, ComposedChart, responsive sizing, custom tooltips, animations
npx skillsauth add agents-inc/skills web-dataviz-rechartsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Recharts wraps D3 in composable React components for declarative charting. Each chart is composed from independent child components (
XAxis,YAxis,Tooltip,Legend,CartesianGrid, data series). UseResponsiveContaineror theresponsiveprop for adaptive sizing. Memoizedataand callback props to avoid unnecessary recalculations. Custom tooltips use thecontentprop. In v3,accessibilityLayerdefaults totrue, and internal state is accessed via hooks, not cloned props.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST wrap charts in ResponsiveContainer or set the responsive prop for adaptive sizing -- charts without responsive handling render at fixed dimensions)
(You MUST memoize data arrays and callback functions passed as props -- unstable references cause Recharts to recalculate all data points)
(You MUST provide explicit width and height to chart components when NOT using ResponsiveContainer -- charts render nothing without dimensions)
(You MUST use the content prop on Tooltip for custom tooltips -- return HTML elements, NOT SVG elements)
</critical_requirements>
Auto-detection: Recharts, recharts, LineChart, BarChart, AreaChart, PieChart, ComposedChart, ScatterChart, RadarChart, ResponsiveContainer, XAxis, YAxis, Tooltip, Legend, CartesianGrid, Line, Bar, Area, Pie, Cell, LabelList, Brush, ReferenceLine, ReferenceArea, customized tooltip, chart data visualization
When to use:
When NOT to use:
Key patterns covered:
ResponsiveContainer vs responsive prop)Detailed Resources:
Recharts treats charts as compositions of independent React components. A LineChart is not a monolith -- it's an assembly of XAxis, YAxis, Tooltip, Legend, CartesianGrid, and one or more Line components. This composable architecture means you add features by adding child components, not by passing configuration objects.
Core principles:
Tooltip component to get tooltips, add CartesianGrid for grid lines. Remove them to remove the feature.data array to the chart, use dataKey on child components to bind to fields.When to use Recharts:
When NOT to use:
Every Recharts chart follows the same composition pattern: a chart container wrapping axis, grid, data series, and overlay components.
import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
} from "recharts";
const CHART_HEIGHT = 400;
const STROKE_WIDTH = 2;
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="month" />
<YAxis />
<Tooltip />
<Legend />
<Line type="monotone" dataKey="revenue" stroke="#8884d8" strokeWidth={STROKE_WIDTH} />
<Line type="monotone" dataKey="expenses" stroke="#82ca9d" strokeWidth={STROKE_WIDTH} />
</LineChart>
</ResponsiveContainer>
Why good: Each child component is an independent feature -- remove Tooltip to remove tooltips, remove CartesianGrid to remove grid lines. Data binding is declarative via dataKey.
See examples/core.md for full chart setup with TypeScript typing.
Charts require explicit dimensions. Two approaches for responsive behavior:
const CHART_HEIGHT = 300;
<ResponsiveContainer width="100%" height={CHART_HEIGHT}>
<BarChart data={data}>
{/* ... */}
</BarChart>
</ResponsiveContainer>
responsive prop (v3+ -- simpler, CSS-based)<BarChart data={data} responsive>
{/* chart uses standard CSS sizing from parent */}
</BarChart>
When to use ResponsiveContainer: When you need debounce, aspect ratio, onResize callback, or minWidth/maxHeight constraints.
When to use responsive prop: When standard CSS sizing from the parent element is sufficient and you want to avoid an extra wrapper.
Gotcha: ResponsiveContainer must have a parent with defined dimensions. If the parent has height: 0 or is display: none, the chart will not render.
See examples/core.md for responsive patterns and SSR considerations.
Use the content prop on Tooltip to render a custom tooltip component. The component receives active, payload, and label props.
import type { TooltipProps } from "recharts";
import type { ValueType, NameType } from "recharts/types/component/DefaultTooltipContent";
function CustomTooltip({ active, payload, label }: TooltipProps<ValueType, NameType>) {
if (!active || !payload?.length) return null;
return (
<div className="custom-tooltip">
<p>{label}</p>
{payload.map((entry) => (
<p key={entry.name} style={{ color: entry.color }}>
{entry.name}: {entry.value}
</p>
))}
</div>
);
}
// Usage
<Tooltip content={<CustomTooltip />} />
Why good: Full control over tooltip markup and styling, TypeScript types from Recharts, HTML elements (not SVG).
Gotcha: Custom tooltip content must return HTML elements, not SVG. Returning SVG causes rendering errors.
See examples/core.md for formatted tooltips and passing extra props.
XAxis and YAxis accept type, dataKey, tickFormatter, domain, and scale for controlling axis behavior.
const CURRENCY_FORMATTER = (value: number) => `$${value.toLocaleString()}`;
const DATE_FORMATTER = (value: string) => new Date(value).toLocaleDateString();
<XAxis
dataKey="date"
tickFormatter={DATE_FORMATTER}
angle={-45}
textAnchor="end"
height={60}
/>
<YAxis
tickFormatter={CURRENCY_FORMATTER}
domain={[0, "dataMax + 1000"]}
width={80}
/>
Key props:
type: "category" (default for XAxis) or "number" (default for YAxis)domain: [min, max] -- accepts numbers, "auto", "dataMin", "dataMax", or expressions like "dataMax + 100"tickFormatter: Function to format tick labelsscale: "auto", "log", "symlog", or custom D3 scaleSee examples/core.md for multi-axis, hidden axes, and label configuration.
PieChart uses the Pie component (not PieChart alone). Use Cell components for per-slice coloring. Set innerRadius for donut style.
import { PieChart, Pie, Cell, Tooltip, Legend } from "recharts";
const COLORS = ["#0088FE", "#00C49F", "#FFBB28", "#FF8042"];
const CHART_SIZE = 400;
const OUTER_RADIUS = 150;
const INNER_RADIUS = 80; // > 0 for donut
<PieChart width={CHART_SIZE} height={CHART_SIZE}>
<Pie
data={data}
dataKey="value"
nameKey="name"
cx="50%"
cy="50%"
outerRadius={OUTER_RADIUS}
innerRadius={INNER_RADIUS}
label
>
{data.map((_, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip />
<Legend />
</PieChart>
Why good: Cell components give per-slice control. innerRadius > 0 creates donut chart. label prop enables sector labels.
See examples/core.md for custom labels and nested pie charts.
Mix different chart types (Line, Bar, Area) in a single chart using ComposedChart.
import { ComposedChart, Line, Bar, Area, XAxis, YAxis, Tooltip, Legend } from "recharts";
<ComposedChart data={data}>
<XAxis dataKey="month" />
<YAxis yAxisId="left" />
<YAxis yAxisId="right" orientation="right" />
<Tooltip />
<Legend />
<Bar dataKey="sales" yAxisId="left" fill="#8884d8" />
<Line type="monotone" dataKey="trend" yAxisId="right" stroke="#ff7300" />
<Area type="monotone" dataKey="forecast" yAxisId="left" fill="#82ca9d" opacity={0.3} />
</ComposedChart>
Why good: Dual Y-axes via yAxisId, different visual types in one chart. Use when data has different scales or units.
See examples/advanced.md for full ComposedChart patterns.
Recharts animates data changes by default. Control with isAnimationActive, animationDuration, and animationEasing on data series components.
const ANIMATION_DURATION = 800;
<Line
dataKey="value"
isAnimationActive={true}
animationDuration={ANIMATION_DURATION}
animationEasing="ease-in-out"
animationBegin={0}
/>
Disable animations for real-time data or performance-critical scenarios:
<Line dataKey="value" isAnimationActive={false} />
Gotcha: When animation is enabled, the entire chart redraws on every data update. For high-frequency updates (>1 update/second), disable animations and use the chart's throttleDelay prop.
See examples/advanced.md for real-time data patterns.
For large datasets or frequent updates, apply these patterns:
// 1. Memoize data to prevent recalculation
const chartData = useMemo(() => transformData(rawData), [rawData]);
// 2. Memoize callback props
const formatTick = useCallback((value: number) => `$${value}`, []);
// 3. Disable animation for frequent updates
<Line dataKey="value" isAnimationActive={false} />
// 4. Throttle mouse events on the chart
<LineChart data={chartData} throttleDelay={100}>
Key strategies:
data arrays -- unstable references force full recalculationdataKey functions -- changes trigger point recalculationthrottleDelay on chart components for mouse event throttlingSee examples/advanced.md for data sampling and throttling patterns.
</patterns><decision_framework>
What relationship are you showing?
|
+-> Change over time?
| +-> Continuous trend -> LineChart or AreaChart
| +-> Discrete periods -> BarChart
| +-> Both overlaid -> ComposedChart
|
+-> Part of a whole?
| +-> Few categories (< 8) -> PieChart
| +-> With center content -> PieChart (donut: innerRadius > 0)
|
+-> Correlation between variables?
| +-> Two variables -> ScatterChart
|
+-> Multi-dimensional comparison?
| +-> 3+ variables per item -> RadarChart
|
+-> Mixing types?
+-> Bar + Line + Area -> ComposedChart
Need debounce, aspect ratio, onResize callback?
+-> YES -> ResponsiveContainer
+-> NO -> responsive prop (v3+, simpler)
</decision_framework>
<red_flags>
High Priority Issues:
width/height props and no ResponsiveContainer. Charts require explicit dimensions.data={fetchedData.map(...)} inline creates a new array every render, forcing full recalculation. Memoize with useMemo.content prop on Tooltip must return HTML elements. SVG elements cause rendering errors.ResponsiveContainer parent has no dimensions -- If the parent has height: 0, the chart will not render. Ensure the parent has defined height.Medium Priority Issues:
dataKey on data series -- Line, Bar, Area, and Pie require dataKey to bind to data fields. Without it, nothing renders.CartesianGrid with non-default axis IDs -- In v3, CartesianGrid requires xAxisId/yAxisId matching the axes. Mismatched IDs produce no grid lines.dataKey -- Causes recalculation on every render. Memoize with useCallback or define outside the component.Cell components -- All slices render in the same default color. Use Cell for per-slice coloring.Gotchas & Edge Cases:
ResponsiveContainer uses ResizeObserver -- may not fire on initial render in some SSR scenarios. Set initialDimension as a fallback.XAxis type="category" is the default -- for numeric axes, explicitly set type="number".domain on YAxis resets when data changes unless you set allowDataOverflow={true}.z-index -- place important elements later in JSX to render on top.syncId synchronizes tooltips and brushes across charts -- all charts with the same syncId share hover state.Brush component enables range selection but adds significant DOM elements. Avoid on dashboards with many charts.label prop can be true (default labels), an element, or a render function -- but complex labels may overlap on small slices. Use LabelList or a custom label function with collision detection.animationBegin defaults to 0 but animations stack -- multiple series animate simultaneously unless you stagger animationBegin.accessibilityLayer defaults to true in v3 -- keyboard controls and ARIA attributes are enabled automatically.</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md
(You MUST wrap charts in ResponsiveContainer or set the responsive prop for adaptive sizing -- charts without responsive handling render at fixed dimensions)
(You MUST memoize data arrays and callback functions passed as props -- unstable references cause Recharts to recalculate all data points)
(You MUST provide explicit width and height to chart components when NOT using ResponsiveContainer -- charts render nothing without dimensions)
(You MUST use the content prop on Tooltip for custom tooltips -- return HTML elements, NOT SVG elements)
Failure to follow these rules will cause charts to render nothing, performance degradation from unnecessary recalculations, and tooltip rendering errors.
</critical_reminders>
development
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
development
Xquik REST API patterns for X post search, user and timeline reads, cursor pagination, media downloads, monitors, signed webhooks, and approval-gated X actions
development
Mapbox GL JS interactive maps - map initialization, markers, popups, sources, layers, expressions, clustering, 3D terrain, geocoding, directions
tools
Leaflet interactive maps - map setup, tile layers, markers, popups, GeoJSON, custom controls, plugins, clustering, events