返回 Skills
ansanabria/skills· MIT 内容可用

recharts

Build composable, responsive React charts with Recharts library. Use when creating data visualizations including line charts, area charts, bar charts, pie charts, scatter plots, and composed charts. Handles chart customization, responsive sizing, tooltips, legends, axes configuration, performance optimization, and accessibility.

安装

与 skills.sh 相同的 Command / Prompt 安装方式


name: recharts description: Build composable, responsive React charts with Recharts library. Use when creating data visualizations including line charts, area charts, bar charts, pie charts, scatter plots, and composed charts. Handles chart customization, responsive sizing, tooltips, legends, axes configuration, performance optimization, and accessibility.

Recharts

React charting library built on top of D3 for composable, declarative data visualization.

Quick Start

1. Install Recharts

npm install recharts

2. Basic Chart Structure

All Recharts charts follow the same pattern:

import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';

const data = [
  { name: 'Jan', sales: 4000, profit: 2400 },
  { name: 'Feb', sales: 3000, profit: 1398 },
  { name: 'Mar', sales: 2000, profit: 9800 },
];

<ResponsiveContainer width="100%" height={300}>
  <LineChart data={data}>
    <CartesianGrid strokeDasharray="3 3" />
    <XAxis dataKey="name" />
    <YAxis />
    <Tooltip />
    <Legend />
    <Line type="monotone" dataKey="sales" stroke="#8884d8" />
    <Line type="monotone" dataKey="profit" stroke="#82ca9d" />
  </LineChart>
</ResponsiveContainer>

Core Concepts

Data Format

Recharts expects data as an array of objects. Each object represents a data point:

const data = [
  { month: 'Jan', revenue: 4000, expenses: 2400 },
  { month: 'Feb', revenue: 3000, expenses: 1398 },
];

Use dataKey props to map object properties to chart components:

  • dataKey="revenue" - maps to the revenue property
  • dataKey={(entry) => entry.revenue - entry.expenses} - function for computed values

Component Composition

Charts are built by nesting specialized components:

Sizing: Use the responsive prop (v3.3+), ResponsiveContainer wrapper, or set width/height directly

Chart types (choose one):

  • LineChart - Line and area visualizations
  • BarChart - Bar and column charts
  • AreaChart - Stacked and filled area charts
  • PieChart - Pie and donut charts
  • ScatterChart - Scatter plots and bubble charts
  • ComposedChart - Mixed chart types
  • RadarChart - Radar/spider charts
  • RadialBarChart - Circular bar charts

Common child components:

  • XAxis / YAxis - Axis configuration
  • CartesianGrid - Grid lines
  • Tooltip - Hover information
  • Legend - Series identification
  • Line / Bar / Area / Pie - Data series visualization

Chart Patterns by Type

Line Charts

<LineChart data={data}>
  <XAxis dataKey="name" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  <Line type="monotone" dataKey="value" stroke="#8884d8" strokeWidth={2} dot={{ r: 4 }} />
</LineChart>

Key props:

  • type: "monotone" (smooth), "linear", "step", "natural"
  • stroke: line color
  • strokeWidth: line thickness
  • dot: point styling (set to false to hide)
  • activeDot: hovered point styling
  • connectNulls: true to connect gaps

Area Charts

<AreaChart data={data}>
  <defs>
    <linearGradient id="colorValue" x1="0" y1="0" x2="0" y2="1">
      <stop offset="5%" stopColor="#8884d8" stopOpacity={0.8}/>
      <stop offset="95%" stopColor="#8884d8" stopOpacity={0}/>
    </linearGradient>
  </defs>
  <XAxis dataKey="name" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Area type="monotone" dataKey="value" stroke="#8884d8" fillOpacity={1} fill="url(#colorValue)" />
</AreaChart>

Stacked areas:

<Area type="monotone" dataKey="sales" stackId="1" stroke="#8884d8" fill="#8884d8" />
<Area type="monotone" dataKey="profit" stackId="1" stroke="#82ca9d" fill="#82ca9d" />

Bar Charts

<BarChart data={data}>
  <XAxis dataKey="name" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  <Bar dataKey="sales" fill="#8884d8" radius={[4, 4, 0, 0]} />
  <Bar dataKey="profit" fill="#82ca9d" radius={[4, 4, 0, 0]} />
</BarChart>

Key props:

  • fill: bar color
  • radius: rounded corners [topLeft, topRight, bottomRight, bottomLeft] or single number for all corners
  • barSize: fixed bar width
  • stackId: group bars into stacks
  • shape: custom bar shape (function or element)

Stacked bars:

<Bar dataKey="sales" stackId="a" fill="#8884d8" />
<Bar dataKey="profit" stackId="a" fill="#82ca9d" />

Rounded stacked bars (use BarStack to round the whole stack):

import { BarStack } from 'recharts';

<BarChart data={data}>
  <BarStack stackId="a" radius={[4, 4, 0, 0]}>
    <Bar dataKey="sales" fill="#8884d8" />
    <Bar dataKey="profit" fill="#82ca9d" />
  </BarStack>
</BarChart>

Pie Charts

const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];

<PieChart>
  <Pie
    data={data}
    dataKey="value"
    nameKey="name"
    cx="50%"
    cy="50%"
    innerRadius={60}
    outerRadius={80}
    paddingAngle={5}
    shape={(props) => <Sector {...props} fill={COLORS[props.index % COLORS.length]} />}
  />
  <Tooltip />
  <Legend />
</PieChart>

Key props:

  • innerRadius: creates donut chart when > 0
  • outerRadius: pie size
  • paddingAngle: gap between slices
  • startAngle / endAngle: partial pie (default: 0 to 360)
  • label: shows values on slices
  • shape: custom render for each slice (replaces deprecated Cell component)

Scatter Charts

<ScatterChart>
  <XAxis type="number" dataKey="x" name="X Axis" />
  <YAxis type="number" dataKey="y" name="Y Axis" />
  <CartesianGrid />
  <Tooltip cursor={{ strokeDasharray: '3 3' }} />
  <Scatter name="Series A" data={data} fill="#8884d8" />
</ScatterChart>

Composed Charts

Mix multiple chart types:

<ComposedChart data={data}>
  <XAxis dataKey="name" />
  <YAxis />
  <CartesianGrid stroke="#f5f5f5" />
  <Tooltip />
  <Legend />
  <Area type="monotone" dataKey="total" fill="#8884d8" stroke="#8884d8" />
  <Bar dataKey="sales" barSize={20} fill="#413ea0" />
  <Line type="monotone" dataKey="profit" stroke="#ff7300" />
</ComposedChart>

Responsive Sizing

Option 1: responsive prop (Recharts 3.3+, recommended)

Set responsive on the chart itself. Uses standard CSS sizing rules:

<LineChart data={data} width="100%" height={300} responsive>
  {/* chart components */}
</LineChart>

Works with flexbox and CSS grid layouts. Also supports CSS style props:

<LineChart data={data} responsive style={{ maxWidth: 800, width: '100%', aspectRatio: '16/9' }}>
  {/* chart components */}
</LineChart>

Option 2: ResponsiveContainer (older versions)

For Recharts < 3.3, wrap chart in ResponsiveContainer:

<ResponsiveContainer width="100%" height={300}>
  <LineChart data={data}>
    {/* chart components */}
  </LineChart>
</ResponsiveContainer>

Critical: ResponsiveContainer must have a parent with defined dimensions. Height must be a number, not a percentage.

Static sizing

Set width and height directly as pixels or percentages:

<LineChart data={data} width={600} height={300}>
  {/* chart components */}
</LineChart>

Axes Configuration

XAxis / YAxis Props

<XAxis 
  dataKey="name"           // property to display
  type="category"          // "category" or "number"
  domain={[0, 'dataMax']}    // axis range
  tick={{ fill: '#666' }}    // tick styling
  tickFormatter={(value) => `$${value}`}  // format labels
  angle={-45}               // rotate labels
  textAnchor="end"         // text alignment
  height={60}              // extra space for labels
/>

Axis Types

  • Category axis (default for X): Treats values as discrete labels
  • Number axis (default for Y): Treats values as continuous scale

Custom Domains

Control axis range:

// Fixed range
<YAxis domain={[0, 100]} />

// Auto with padding
<YAxis domain={[0, 'auto']} />

// Data-based with overflow allowed
<YAxis domain={[0, 'dataMax + 100']} allowDataOverflow />

// Logarithmic scale
<YAxis type="number" scale="log" domain={['auto', 'auto']} />

Customization

Custom Tooltip

const CustomTooltip = ({ active, payload, label }) => {
  if (active && payload && payload.length) {
    return (
      <div className="custom-tooltip">
        <p className="label">{`${label}`}</p>
        <p className="intro">{`Sales: ${payload[0].value}`}</p>
        <p className="desc">Additional info...</p>
      </div>
    );
  }
  return null;
};

<Tooltip content={<CustomTooltip />} />

Custom Legend

const CustomLegend = ({ payload }) => (
  <ul>
    {payload.map((entry, index) => (
      <li key={`item-${index}`} style={{ color: entry.color }}>
        {entry.value}
      </li>
    ))}
  </ul>
);

<Legend content={<CustomLegend />} />

Custom Shapes

Custom bar shape:

const CustomBar = (props) => {
  const { x, y, width, height, fill } = props;
  return <path d={`M${x},${y} ...`} fill={fill} />;
};

<Bar shape={<CustomBar />} dataKey="sales" />
// OR
<Bar shape={(props) => <CustomBar {...props} />} dataKey="sales" />

Custom Labels

<Line 
  dataKey="sales" 
  label={{ position: 'top', fill: '#666', fontSize: 12 }}
/>

// Custom label component
<Line 
  dataKey="sales" 
  label={<CustomLabel />}
/>

Styling

Chart styles:

<LineChart style={{ backgroundColor: '#f5f5f5' }}>

Axis styling:

<XAxis 
  axisLine={{ stroke: '#666' }}
  tickLine={{ stroke: '#666' }}
  tick={{ fill: '#666', fontSize: 12 }}
/>

Grid styling:

<CartesianGrid strokeDasharray="3 3" stroke="#e0e0e0" />

Interactions

Active Elements and Interaction Control

The Tooltip component controls active element highlighting. Do not use activeIndex prop (removed in v3).

Tooltip interaction props:

  • defaultIndex: Sets initial highlighted item on render
  • active: If true, tooltip remains active after interaction ends
  • trigger: "hover" (default) or "click" for click-based interaction
  • content: Custom content or () => null to hide tooltip text while keeping highlight
  • cursor: Visual cursor in plot area, set to false to hide
{/* Click-based interaction with hidden tooltip text */}
<Tooltip trigger="click" content={() => null} cursor={false} />

{/* Default highlighted item on render */}
<Tooltip defaultIndex={2} />

Click Events

<LineChart onClick={(e) => console.log(e)}>
  <Bar 
    dataKey="sales" 
    onClick={(data, index) => console.log('Bar clicked:', data)}
  />
</LineChart>

Synchronized Charts

Link multiple charts with syncId:

<LineChart data={data1} syncId="anyId">
  {/* components */}
</LineChart>

<LineChart data={data2} syncId="anyId">
  {/* components - tooltips synchronize */}
</LineChart>

Brush for Zooming

<LineChart data={data}>
  {/* other components */}
  <Brush dataKey="name" height={30} stroke="#8884d8" />
</LineChart>

Performance Optimization

1. Stable References

Use useMemo and useCallback for props:

// BAD - new function on every render
<Line dataKey={(entry) => entry.sales * 2} />

// GOOD - stable reference
const dataKey = useCallback((entry) => entry.sales * 2, []);
<Line dataKey={dataKey} />

2. Memoize Components

const MemoizedChart = React.memo(({ data }) => (
  <LineChart data={data}>
    {/* components */}
  </LineChart>
));

3. Isolate Changing Components

Separate frequently updating components:

const Chart = () => {
  const [hoveredData, setHoveredData] = useState(null);
  
  return (
    <LineChart>
      {/* Static components */}
      <Line dataKey="sales" />
      
      {/* Dynamic overlay */}
      <ReferenceLine x={hoveredData?.x} stroke="red" />
    </LineChart>
  );
};

4. Debounce Events

import { useDebouncedCallback } from 'use-debounce';

const handleMouseMove = useDebouncedCallback((e) => {
  setPosition(e.activeLabel);
}, 10);

<LineChart onMouseMove={handleMouseMove}>

5. Reduce Data Points

For large datasets, consider aggregation:

// Bin data before rendering
const binnedData = useMemo(() => {
  return d3.bin().value(d => d.x)(rawData);
}, [rawData]);

Accessibility

Recharts includes built-in accessibility support:

<LineChart accessibilityLayer={true}>
  <Line dataKey="sales" name="Monthly Sales" />
</LineChart>

Accessibility is enabled by default. The chart is keyboard navigable and screen reader compatible.

ARIA props:

<LineChart role="img" aria-label="Sales chart showing monthly revenue">

Common Patterns

Multiple Data Series

<LineChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <Tooltip />
  <Legend />
  <Line type="monotone" dataKey="productA" name="Product A" stroke="#8884d8" />
  <Line type="monotone" dataKey="productB" name="Product B" stroke="#82ca9d" />
  <Line type="monotone" dataKey="productC" name="Product C" stroke="#ffc658" />
</LineChart>

Horizontal Bar Chart

<BarChart layout="vertical" data={data}>
  <XAxis type="number" />
  <YAxis type="category" dataKey="name" />
  <Bar dataKey="value" />
</BarChart>

Donut Chart

const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];

<PieChart>
  <Pie
    data={data}
    innerRadius={60}
    outerRadius={80}
    paddingAngle={5}
    dataKey="value"
    shape={(props) => <Sector {...props} fill={COLORS[props.index % COLORS.length]} />}
  />
</PieChart>

Note: Cell component is deprecated and will be removed in Recharts 4.0. Use the shape prop on Bar, Pie, Scatter, etc. instead.

Reference Lines/Areas

<LineChart data={data}>
  {/* ... */}
  <ReferenceLine y={5000} label="Target" stroke="red" strokeDasharray="3 3" />
  <ReferenceArea x1="Jan" x2="Mar" fill="#8884d8" fillOpacity={0.1} />
</LineChart>

Error Bars

<ScatterChart>
  <Scatter data={data}>
    <ErrorBar dataKey="errorX" width={4} strokeWidth={2} />
    <ErrorBar dataKey="errorY" width={4} strokeWidth={2} direction="y" />
  </Scatter>
</ScatterChart>

Integration Patterns

With State Management

const SalesChart = () => {
  const [timeRange, setTimeRange] = useState('month');
  const data = useSelector(state => selectSalesData(state, timeRange));
  
  return (
    <ResponsiveContainer>
      <LineChart data={data}>
        {/* components */}
      </LineChart>
    </ResponsiveContainer>
  );
};

With Real-time Data

const RealtimeChart = () => {
  const [data, setData] = useState([]);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setData(prev => [...prev.slice(-20), newDataPoint]);
    }, 1000);
    return () => clearInterval(interval);
  }, []);
  
  return (
    <LineChart data={data}>
      <XAxis dataKey="time" />
      <YAxis domain={['auto', 'auto']} />
      <Line type="monotone" dataKey="value" isAnimationActive={false} />
    </LineChart>
  );
};

Z-Index and Layering (v3.4+)

Components render in a default order (grid < axes < chart elements < tooltip/legend). Override with zIndex prop:

<Line dataKey="sales" zIndex={10} />  // Render on top

For components without direct zIndex support, wrap in ZIndexLayer:

import { ZIndexLayer } from 'recharts';

<ZIndexLayer zIndex={5}>
  <CustomAnnotation />
</ZIndexLayer>

Coordinate Systems

Recharts has three coordinate systems:

  1. Domain coordinates - Data values (e.g., x="March", y=5000). Used by ReferenceLine, ReferenceDot, ReferenceArea. Automatically converted to pixels.
  2. Pixel coordinates - Positions relative to chart viewBox. Used for custom SVG shapes. Access via usePlotArea(), useOffset(), useChartWidth() hooks.
  3. Mouse event coordinates - Browser viewport coordinates. Convert with getRelativeCoordinate(event, element).

Converting between systems:

  • Data to pixels: useXAxisScale(), useYAxisScale()
  • Pixels to data: useXAxisInverseScale(), useYAxisInverseScale()

Troubleshooting

Chart Not Rendering

  • Ensure ResponsiveContainer has a parent with defined dimensions
  • Check that height is a number (not percentage in ResponsiveContainer)
  • Verify data is an array of objects

Tooltip Not Showing

  • Ensure Tooltip component is included
  • Check that dataKey values exist in data objects

Axis Labels Overlapping

  • Rotate labels: <XAxis angle={-45} textAnchor="end" height={80} />
  • Use interval: <XAxis interval={0} /> (0 = show all, 'preserveStartEnd' = auto)

Animation Issues

  • Disable: <Line isAnimationActive={false} />
  • Reduce duration: <Line animationDuration={500} />

Resources

References

External Resources

附带文件

references/api_reference.md
# Recharts API Reference

Complete reference for all Recharts components, props, and configuration options.

## Table of Contents

1. [Chart Components](#chart-components)
2. [Cartesian Components](#cartesian-components)
3. [Polar Components](#polar-components)
4. [General Components](#general-components)
5. [Hooks](#hooks)
6. [Shapes](#shapes)

## Chart Components

### LineChart

Line and area visualizations with support for multiple series, tooltips, and animations.

```jsx
<LineChart
  data={array}              // Required: data array
  width={number}            // Width in px or percentage string
  height={number}           // Height in px or percentage string
  layout="horizontal"       // "horizontal" | "vertical"
  margin={{ top, right, bottom, left }}
  responsive={boolean}      // Auto-resize with container (v3.3+, recommended)
  style={object}            // CSS styles (useful with responsive for maxWidth, aspectRatio, etc.)
  accessibilityLayer={true} // Keyboard navigation and screen reader support (default: true)
  syncId="string"          // Synchronize with other charts
  onClick={func}
  onMouseMove={func}
  onMouseEnter={func}
  onMouseLeave={func}
>
```

**Child components**: XAxis, YAxis, CartesianGrid, Tooltip, Legend, Line, ReferenceLine, ReferenceArea, ReferenceDot, Brush

**Note**: The `responsive`, `style`, and `accessibilityLayer` props are available on all chart types (BarChart, AreaChart, PieChart, ScatterChart, ComposedChart, RadarChart, etc.).

### BarChart

Bar and column charts with stacking, grouping, and custom shapes.

```jsx
<BarChart
  data={array}
  layout="horizontal"
  barCategoryGap="10%"      // Gap between categories
  barGap={4}               // Gap between bars in same category
  barSize={number}         // Fixed bar width
  maxBarSize={number}      // Maximum bar width
  stackOffset="none"       // "none" | "expand" | "positive" | "sign" | "silhouette" | "wiggle"
>
```

**Key props**:
- `barCategoryGap`: Percentage or number for category spacing
- `barGap`: Pixels between bars in same group
- `barSize`: Fixed width/height (auto-calculated if not set)
- `stackOffset`: Strategy for stacked bars

### AreaChart

Filled area charts with gradients and stacking.

```jsx
<AreaChart
  data={array}
  baseValue="dataMin"      // Base for area fill: "dataMin" | "dataMax" | number
  stackOffset="none"
>
```

### PieChart

Pie and donut charts for proportional data.

```jsx
<PieChart
  width={number}
  height={number}
>
  <Pie
    data={array}
    dataKey="value"         // Required: numeric property
    nameKey="name"          // Property for labels
    cx="50%"               // Center X
    cy="50%"               // Center Y
    innerRadius={0}        // For donut chart
    outerRadius={number}    // Pie radius
    startAngle={0}         // Starting angle (degrees)
    endAngle={360}         // Ending angle
    minAngle={0}           // Minimum slice angle
    paddingAngle={0}       // Gap between slices
    label={false}          // Show labels
    labelLine={true}       // Line connecting labels
    isAnimationActive={true}
  />
</PieChart>
```

### ScatterChart

Scatter plots and bubble charts for correlated data.

```jsx
<ScatterChart
  width={number}
  height={number}
  margin={{ top, right, bottom, left }}
>
  <XAxis type="number" dataKey="x" />
  <YAxis type="number" dataKey="y" />
  <Scatter
    data={array}
    dataKey="y"
    fill="#8884d8"
    shape="circle"         // "circle" | "cross" | "diamond" | "square" | "star" | "triangle" | "wye" | function
    legendType="circle"
  />
</ScatterChart>
```

### ComposedChart

Mix multiple chart types (lines, bars, areas) in one chart.

```jsx
<ComposedChart data={array}>
  {/* Can include: Area, Bar, Line, Scatter, XAxis, YAxis, etc. */}
</ComposedChart>
```

### RadarChart

Radar/spider charts for multi-dimensional data.

```jsx
<RadarChart
  cx="50%"
  cy="50%"
  outerRadius={number}
  width={number}
  height={number}
  data={array}
>
  <PolarGrid />
  <PolarAngleAxis dataKey="subject" />
  <PolarRadiusAxis />
  <Radar
    name="Series"
    dataKey="A"
    stroke="#8884d8"
    fill="#8884d8"
    fillOpacity={0.6}
  />
</RadarChart>
```

### RadialBarChart

Circular bar charts.

```jsx
<RadialBarChart
  width={number}
  height={number}
  cx="50%"
  cy="50%"
  innerRadius={number}
  outerRadius={number}
  data={array}
  startAngle={90}
  endAngle={-270}
>
  <RadialBar dataKey="value" background clockWise />
  <Legend />
  <Tooltip />
</RadialBarChart>
```

### Treemap

Hierarchical data visualization.

```jsx
<Treemap
  width={number}
  height={number}
  data={array}
  dataKey="size"
  stroke="#fff"
  fill="#8884d8"
  aspectRatio={number}
  content={func}           // Custom render function
/>
```

### Sankey

Flow diagram for visualizing flow between nodes.

```jsx
<Sankey
  width={number}
  height={number}
  data={sankeyData}        // { nodes: [], links: [] }
  nodePadding={number}
  nodeWidth={number}
  linkCurvature={number}
  iterations={number}
>
```

### SunburstChart

Radial hierarchy visualization.

```jsx
<SunburstChart
  data={hierarchicalData}
  dataKey="value"
/>
```

## Cartesian Components

### XAxis / YAxis

Configure axes for Cartesian charts.

```jsx
<XAxis
  dataKey="name"          // Property for tick labels
  type="category"         // "category" | "number"
  domain={['auto', 'auto']}  // [min, max]
  range={array}          // Custom range
  scale="auto"           // "auto" | "linear" | "pow" | "sqrt" | "log" | "identity" | "time" | "band" | "point" | "ordinal" | function
  tick={object|element}   // Tick style or custom element
  tickLine={true}        // Show tick lines
  axisLine={true}        // Show axis line
  tickFormatter={func}    // Format tick labels
  ticks={array}          // Custom tick values
  interval="preserveEnd"  // "preserveStart" | "preserveEnd" | "preserveStartEnd" | number
  angle={0}              // Rotate labels
  height={30}            // Reserved height
  width={60}             // Reserved width
  label={{ value: 'text', position: 'insideBottom', offset: -10 }}
  orientation="bottom"    // "top" | "bottom" (XAxis) | "left" | "right" (YAxis)
  allowDataOverflow={false}
  allowDecimals={true}
  allowDuplicatedCategory={true}
  hide={false}
  mirror={false}
  reversed={false}
/>
```

### Line

Line series for LineChart and ComposedChart.

```jsx
<Pie
  data={array}
  dataKey="value"         // Required: numeric property
  nameKey="name"          // Property for labels
  cx="50%"               // Center X
  cy="50%"               // Center Y
  innerRadius={0}        // For donut chart
  outerRadius={number}    // Pie radius
  startAngle={0}         // Starting angle (degrees)
  endAngle={360}         // Ending angle
  minAngle={0}           // Minimum slice angle
  paddingAngle={0}       // Gap between slices
  label={false}          // Show labels
  labelLine={true}       // Line connecting labels
  shape={element|func}   // Custom slice render; receives isActive prop for active/inactive styling (replaces deprecated Cell, activeShape, inactiveShape)
  isAnimationActive={true}
/>
```

### Bar

Bar series for BarChart and ComposedChart.

```jsx
<Bar
  dataKey="value"
  name="Series Name"
  xAxisId={0}
  yAxisId={0}
  legendType="rect"
  stackId="a"           // Group into stacks
  barSize={20}          // Fixed bar size
  unit="k"              // Unit suffix
  fill="#8884d8"
  stroke="#8884d8"
  strokeWidth={1}
  radius={[4, 4, 0, 0]}  // Corner radii [tl, tr, br, bl]
  label={false}
  isAnimationActive={true}
  animationBegin={0}
  animationDuration={1500}
  animationEasing="ease"
  hide={false}
  background={false}    // Show background bars
  shape={element|func}  // Custom bar shape
  onClick={func}
  onMouseEnter={func}
  onMouseLeave={func}
/>
```

### Area

Area series for AreaChart and ComposedChart.

```jsx
<Area
  type="monotone"
  dataKey="value"
  name="Series Name"
  xAxisId={0}
  yAxisId={0}
  stackId="a"           // Stack areas
  unit="k"
  stroke="#8884d8"
  strokeWidth={1}
  fill="#8884d8"        // Solid fill
  fillOpacity={0.6}     // Opacity
  fill="url(#gradient)" // Gradient fill
  dot={false}
  activeDot={{ r: 8 }}
  label={false}
  isAnimationActive={true}
  animationDuration={1500}
  animationEasing="ease"
  legendType="line"
  connectNulls={false}
  hide={false}
  baseLine={number}     // Base value for fill
  onClick={func}
  onMouseEnter={func}
/>
```

### Scatter

Scatter plot points.

```jsx
<Scatter
  data={array}
  dataKey="y"
  name="Series Name"
  xAxisId={0}
  yAxisId={0}
  zAxisId={0}
  legendType="circle"
  line={false}          // Connect points with line
  lineType="joint"      // "joint" | "fitting"
  shape="circle"        // Shape or custom function
  fill="#8884d8"
  stroke="#8884d8"
  isAnimationActive={true}
  onClick={func}
>
  <ErrorBar dataKey="error" direction="x" />
  <ErrorBar dataKey="error" direction="y" />
</Scatter>
```

### CartesianGrid

Grid lines for Cartesian charts.

```jsx
<CartesianGrid
  strokeDasharray="3 3"  // Line pattern
  stroke="#ccc"         // Line color
  fill="none"           // Grid fill
  horizontal={true}     // Horizontal lines
  vertical={true}       // Vertical lines
  horizontalCoordinatesGenerator={func}
  verticalCoordinatesGenerator={func}
  x={number}
  y={number}
  width={number}
  height={number}
/>
```

### ReferenceLine

Horizontal or vertical reference line.

```jsx
<ReferenceLine
  x="value"             // X position for vertical line
  y={5000}              // Y position for horizontal line
  xAxisId={0}
  yAxisId={0}
  alwaysShow={false}
  isFront={false}       // Render on top
  stroke="red"
  strokeWidth={1}
  strokeDasharray="3 3"
  label={{ value: "Label", position: "center", fill: "red" }}
/>
```

### ReferenceArea

Highlighted rectangular region.

```jsx
<ReferenceArea
  x1="Jan"              // Start X
  x2="Mar"              // End X
  y1={0}                // Start Y
  y2={100}              // End Y
  xAxisId={0}
  yAxisId={0}
  alwaysShow={false}
  isFront={false}
  stroke="#8884d8"
  strokeWidth={1}
  fill="#8884d8"
  fillOpacity={0.3}
  label={{ value: "Area" }}
/>
```

### ReferenceDot

Highlighted point marker.

```jsx
<ReferenceDot
  x="value"
  y={number}
  xAxisId={0}
  yAxisId={0}
  isFront={false}
  alwaysShow={false}
  r={10}                // Radius
  stroke="#8884d8"
  strokeWidth={2}
  fill="#fff"
  label={{ value: "Point" }}
/>
```

### Brush

Zoom/scroll control for charts.

```jsx
<Brush
  dataKey="name"        // X-axis data key
  width={number}        // Brush width
  height={30}           // Brush height
  x={number}            // X position
  y={number}            // Y position
  startIndex={0}        // Initial start
  endIndex={data.length - 1}
  travellerWidth={5}    // Handle width
  stroke="#8884d8"
  fill="#fff"
  gap={1}               // Gap between items
  onChange={func}       // Selection change callback
  onDragEnd={func}
/>
```

### ErrorBar

Error indicators for scatter and bar charts.

```jsx
<ErrorBar
  dataKey="error"
  direction="x"         // "x" | "y"
  width={5}             // Error bar width
  strokeWidth={2}
/>
```

### ZAxis

Third dimension for bubble charts.

```jsx
<ZAxis
  type="number"
  dataKey="z"
  range={[60, 400]}     // Bubble size range
  unit="units"
/>
```

### Funnel

Funnel chart component (usually in FunnelChart).

```jsx
<Funnel
  dataKey="value"
  data={array}
  nameKey="name"
  isAnimationActive={true}
  animationDuration={1500}
  legendType={string}
/>
```

## Polar Components

### Pie

Pie chart slices.

```jsx
<Pie
  data={array}
  dataKey="value"
  nameKey="name"
  cx="50%"
  cy="50%"
  innerRadius={0}
  outerRadius={number}
  paddingAngle={0}
  startAngle={0}
  endAngle={360}
  minAngle={0}
  cornerRadius={0}      // Rounded corners
  cornerIsExternal={false}
  label={false}         // boolean | object | element | function
  labelLine={true}
  activeIndex={array}   // Currently active slice(s) — DEPRECATED in v3, use Tooltip defaultIndex instead
  activeShape={element|func}  // Active slice style — DEPRECATED, use shape prop with isActive
  shape={element|func}  // Custom slice render; receives isActive for active/inactive styling (replaces deprecated Cell, activeShape, inactiveShape)
  isAnimationActive={true}
  animationBegin={0}
  animationDuration={1500}
  animationEasing="ease"
  onClick={func}
  onMouseEnter={func}
/>

// Per-slice colors using shape prop (replaces deprecated Cell):
<Pie
  data={data}
  dataKey="value"
  shape={(props) => <Sector {...props} fill={COLORS[props.index % COLORS.length]} />}
/>
```

### Radar

Radar chart polygon.

```jsx
<Radar
  name="Series"
  dataKey="value"
  stroke="#8884d8"
  strokeWidth={1}
  fill="#8884d8"
  fillOpacity={0.6}
  isAnimationActive={true}
  legendType="line"
  dot={false}
/>
```

### RadialBar

Radial bar segments.

```jsx
<RadialBar
  dataKey="value"
  background={false}
  clockWise={true}
  minAngle={0}
  cornerRadius={0}
  isAnimationActive={true}
  legendType="circle"
/>
```

### PolarGrid

Grid for radar charts.

```jsx
<PolarGrid
  cx={number}
  cy={number}
  outerRadius={number}
  gridType="polygon"    // "polygon" | "circle"
/>
```

### PolarAngleAxis

Angular axis for radar charts.

```jsx
<PolarAngleAxis
  dataKey="subject"
  type="category"
  tick={object|element}
  tickFormatter={func}
/>
```

### PolarRadiusAxis

Radial axis for radar charts.

```jsx
<PolarRadiusAxis
  type="number"
  domain={[0, 'auto']}
  tick={object}
  tickFormatter={func}
  label={{ value: 'Label', angle: 90 }}
/>
```

## General Components

### ResponsiveContainer

Makes charts responsive to container size. **For Recharts < 3.3.** In Recharts 3.3+, prefer the `responsive` prop on chart components instead.

```jsx
<ResponsiveContainer
  width="100%"           // "100%" | number
  height={300}          // Required: number (NOT percentage)
  aspect={number}        // Aspect ratio (alternative to height)
  minWidth={number}
  minHeight={number}
  maxHeight={number}
  debounce={number}      // Resize debounce (ms)
  className={string}
  style={object}
>
  {/* Chart component */}
</ResponsiveContainer>
```

**Critical**: Height must be a number, not percentage. Parent element must have defined dimensions.

### Tooltip

Hover/click information display. Also controls active element highlighting (replaces removed `activeIndex` prop from v2).

```jsx
<Tooltip
  trigger="hover"         // "hover" (default) | "click"
  defaultIndex={number}   // Initial highlighted item index on render
  active={boolean}        // Force tooltip to stay active
  cursor={{ stroke: '#ccc', strokeWidth: 1 }}  // Cursor style, false to hide
  content={element|func}  // Custom content, () => null to hide text
  contentStyle={object}   // Container styles
  wrapperStyle={object}
  labelStyle={object}
  itemStyle={object}
  separator={" : "}
  formatter={(value, name, props) => [formattedValue, formattedName]}
  labelFormatter={(label) => formattedLabel}
  isAnimationActive={true}
  animationDuration={500}
  animationEasing="ease"
  itemSorter={func}       // Sort tooltip items
  filterNull={true}       // Hide null values
/>
```

**Custom Tooltip**:
```jsx
const CustomTooltip = ({ active, payload, label }) => {
  if (active && payload && payload.length) {
    return (
      <div className="custom-tooltip">
        <p className="label">{label}</p>
        {payload.map((entry, index) => (
          <p key={index} style={{ color: entry.color }}>
            {entry.name}: {entry.value}
          </p>
        ))}
      </div>
    );
  }
  return null;
};
```

### Legend

Series identification.

```jsx
<Legend
  layout="horizontal"     // "horizontal" | "vertical"
  align="center"         // "left" | "center" | "right"
  verticalAlign="bottom"  // "top" | "middle" | "bottom"
  iconType="line"         // "line" | "square" | "rect" | "circle" | "cross" | "diamond" | "star" | "triangle" | "wye"
  iconSize={14}
  content={element|func}  // Custom content
  payload={array}         // Custom data
  wrapperStyle={object}
  chartWidth={number}
  chartHeight={number}
  onClick={func}
  onMouseEnter={func}
  onMouseLeave={func}
/>
```

**Custom Legend**:
```jsx
const CustomLegend = ({ payload }) => (
  <ul>
    {payload.map((entry, index) => (
      <li key={`item-${index}`} style={{ color: entry.color }}>
        {entry.value}
      </li>
    ))}
  </ul>
);
```

### Label

Individual data point label.

```jsx
<Label
  value="Text"           // Label text
  position="top"         // "top" | "left" | "right" | "bottom" | "inside" | "outside" | "center"
  offset={5}             // Distance from element
  fill="#666"
  fontSize={12}
  formatter={func}
/>
```

### LabelList

List of labels for data series.

```jsx
<LabelList
  dataKey="value"        // Property for label text
  position="top"         // Label position
  offset={10}
  fill="#666"
  fontSize={12}
  formatter={func}       // Format function
  content={element|func}   // Custom label
/>

// Usage within series
<Bar dataKey="sales">
  <LabelList dataKey="sales" position="top" />
</Bar>
```

### Cell (DEPRECATED - removed in Recharts 4.0)

**Do not use in new code.** Use the `shape` prop on `Bar`, `Pie`, `Scatter`, etc. instead.

```jsx
// OLD (deprecated):
{data.map((entry, index) => (
  <Cell key={`cell-${index}`} fill={colors[index]} />
))}

// NEW (use shape prop):
<Bar dataKey="sales" shape={(props) => <Rectangle {...props} fill={colors[props.index]} />} />
<Pie dataKey="value" shape={(props) => <Sector {...props} fill={colors[props.index]} />} />
```

### Text

SVG text element.

```jsx
<Text
  x={number}
  y={number}
  textAnchor="start"      // "start" | "middle" | "end"
  width={number}          // Max width for wrapping
  scaleToFit={false}      // Scale text to fit width
  angle={0}               // Rotation
  lineHeight={string}     // Line height for multi-line
  capHeight={string}      // Capital letter height
  fill="#666"
  fontSize={14}
>
  Text content
</Text>
```

### Customized

Custom SVG elements with chart context.

```jsx
<Customized component={<CustomComponent />} />
```

### Layer

SVG group element.

```jsx
<Layer x={0} y={0} className={string}>
  {/* SVG elements */}
</Layer>
```

## Hooks

### useIsTooltipActive

```jsx
const isActive = useIsTooltipActive();
```

Returns boolean indicating if tooltip is currently active.

### useActiveTooltipCoordinate

```jsx
const coordinate = useActiveTooltipCoordinate();
// { x: number, y: number }
```

Returns coordinate of active tooltip.

### useActiveTooltipDataPoints

```jsx
const dataPoints = useActiveTooltipDataPoints();
```

Returns data points at active tooltip position.

### useActiveTooltipLabel

```jsx
const label = useActiveTooltipLabel();
```

Returns label of active tooltip.

### useCartesianScale

```jsx
const scale = useCartesianScale();
```

Returns Cartesian coordinate scale information.

### useXAxisScale / useYAxisScale

```jsx
const xScale = useXAxisScale(xAxisId);
const yScale = useYAxisScale(yAxisId);
```

Returns specific axis scale (data values to pixel coordinates).

### useXAxisInverseScale / useYAxisInverseScale

```jsx
const xInverse = useXAxisInverseScale(xAxisId);
const yInverse = useYAxisInverseScale(yAxisId);
```

Returns inverse scale (pixel coordinates to data values).

### useXAxisInverseDataSnapScale / useYAxisInverseDataSnapScale

```jsx
const xSnap = useXAxisInverseDataSnapScale(xAxisId);
const ySnap = useYAxisInverseDataSnapScale(yAxisId);
```

Returns inverse scale that snaps to nearest data point.

### useXAxisInverseTickSnapScale / useYAxisInverseTickSnapScale

```jsx
const xTickSnap = useXAxisInverseTickSnapScale(xAxisId);
const yTickSnap = useYAxisInverseTickSnapScale(yAxisId);
```

Returns inverse scale that snaps to nearest tick value.

### useXAxisDomain / useYAxisDomain

```jsx
const xDomain = useXAxisDomain(xAxisId);
const yDomain = useYAxisDomain(yAxisId);
```

Returns axis domain.

### useXAxisTicks / useYAxisTicks

```jsx
const xTicks = useXAxisTicks(xAxisId);
const yTicks = useYAxisTicks(yAxisId);
```

Returns axis tick information.

### useMargin

```jsx
const margin = useMargin();
// { top, right, bottom, left }
```

Returns chart margin.

### useOffset

```jsx
const offset = useOffset();
// { top, left }
```

Returns chart offset.

### usePlotArea

```jsx
const plotArea = usePlotArea();
// { x, y, width, height }
```

Returns plot area dimensions.

### useChartWidth / useChartHeight

```jsx
const width = useChartWidth();
const height = useChartHeight();
```

Returns chart dimensions.

## Shapes

### Rectangle

```jsx
<Rectangle
  x={number}
  y={number}
  width={number}
  height={number}
  radius={[tl, tr, br, bl]}
  fill="none"
  stroke="#000"
  strokeWidth={1}
/>
```

### Circle / Dot

```jsx
<Dot
  cx={number}
  cy={number}
  r={number}
  fill="#8884d8"
  stroke="#8884d8"
  strokeWidth={1}
/>
```

### Sector

```jsx
<Sector
  cx={number}
  cy={number}
  innerRadius={number}
  outerRadius={number}
  startAngle={number}
  endAngle={number}
  fill="#8884d8"
/>
```

### Symbols

```jsx
<Symbols
  cx={number}
  cy={number}
  size={number}
  type="circle"         // "circle" | "cross" | "diamond" | "square" | "star" | "triangle" | "wye"
  fill="#8884d8"
/>
```

### Polygon

```jsx
<Polygon
  points={[{x, y}, ...]}
  fill="none"
  stroke="#000"
/>
```

### Curve

```jsx
<Curve
  type="monotone"
  points={[{x, y}, ...]}
  stroke="#8884d8"
  fill="none"
/>
```

### Cross

```jsx
<Cross
  x={number}
  y={number}
  width={number}
  height={number}
  stroke="#000"
/>
```

### Trapezoid

```jsx
<Trapezoid
  x={number}
  y={number}
  upperWidth={number}
  lowerWidth={number}
  height={number}
  fill="#8884d8"
/>
```

## Utility Functions

### getNiceTickValues

Generate nice axis tick values.

```jsx
import { getNiceTickValues } from 'recharts';

const ticks = getNiceTickValues([0, 100], 5);
// [0, 20, 40, 60, 80, 100]
```

### getRelativeCoordinate

Convert screen coordinates to chart coordinates.

```jsx
import { getRelativeCoordinate } from 'recharts';

const chartPoint = getRelativeCoordinate(event, chartContainer);
// { x, y }
```

## Global Configuration

### RechartsGlobal

Configure global defaults.

```jsx
import { Global } from 'recharts';

<Global 
  isSsrMode={false}      // Server-side rendering mode
/>
```

## Z-Index and Layering

### ZIndexLayer

```jsx
<ZIndexLayer zIndex={number}>
  {/* Components at this z-index */}
</ZIndexLayer>
```

### Default Z-Index Values

Default layer ordering:
- Grid: 0
- Axes: 1
- Chart elements: 2
- Tooltip/Legend: 5

Use `isFront` prop on reference elements to render above chart.
references/best_practices.md
# Recharts Best Practices

Design, performance, and accessibility guidelines for building production-ready charts with Recharts.

## Table of Contents

1. [Performance Optimization](#performance-optimization)
2. [Responsive Design](#responsive-design)
3. [Accessibility](#accessibility)
4. [Data Patterns](#data-patterns)
5. [Visual Design](#visual-design)
6. [Testing and Debugging](#testing-and-debugging)
7. [Common Pitfalls](#common-pitfalls)

## Performance Optimization

### 1. Memoize Data and Props

Always use `useMemo` for data transformations and `useCallback` for event handlers:

```jsx
// GOOD: Stable data reference
const processedData = useMemo(() => {
  return rawData.map(item => ({
    ...item,
    total: item.revenue + item.expenses
  }));
}, [rawData]);

// GOOD: Stable callback
const handleClick = useCallback((data) => {
  console.log('Clicked:', data);
}, []);

// GOOD: Stable dataKey function
const dataKeyFn = useCallback((entry) => entry.value * 100, []);

<LineChart data={processedData}>
  <Line dataKey={dataKeyFn} onClick={handleClick} />
</LineChart>
```

**Why this matters**: Recharts compares props by reference. New function references on each render trigger unnecessary recalculations.

### 2. Memoize Components

Wrap chart components with `React.memo` when they receive stable props:

```jsx
const MemoizedChart = React.memo(({ data }) => (
  <LineChart data={data}>
    <XAxis dataKey="name" />
    <YAxis />
    <Line type="monotone" dataKey="value" />
  </LineChart>
));

// Parent component
function Dashboard() {
  const [data] = useState(initialData);
  
  return <MemoizedChart data={data} />; // Won't re-render if data is stable
}
```

### 3. Isolate Frequently Updating Components

Separate static and dynamic chart parts:

```jsx
function OptimizedChart() {
  const [hoveredPoint, setHoveredPoint] = useState(null);
  
  // Debounced hover handler
  const handleMouseMove = useDebouncedCallback((e) => {
    if (e && e.activePayload) {
      setHoveredPoint(e.activePayload[0]);
    }
  }, 50);
  
  return (
    <LineChart data={data} onMouseMove={handleMouseMove}>
      {/* Static - rarely changes */}
      <CartesianGrid strokeDasharray="3 3" />
      <XAxis dataKey="name" />
      <YAxis />
      <Tooltip />
      <Line type="monotone" dataKey="sales" stroke="#8884d8" />
      
      {/* Dynamic - changes often */}
      {hoveredPoint && (
        <ReferenceLine 
          x={hoveredPoint.payload.name} 
          stroke="#ff7300" 
          strokeDasharray="3 3"
        />
      )}
    </LineChart>
  );
}
```

### 4. Reduce Data Points for Large Datasets

For datasets with thousands of points, aggregate or sample:

```jsx
import * as d3 from 'd3';

function OptimizedLargeChart({ rawData }) {
  // Sample data if too large
  const data = useMemo(() => {
    if (rawData.length <= 500) return rawData;
    
    // Use d3.bin for histogram or simple sampling
    const step = Math.ceil(rawData.length / 500);
    return rawData.filter((_, i) => i % step === 0);
  }, [rawData]);
  
  // Or use binning for distributions
  const binnedData = useMemo(() => {
    if (rawData.length <= 500) return rawData;
    
    const bin = d3.bin()
      .value(d => d.x)
      .thresholds(50);
    
    return bin(rawData).map(b => ({
      x0: b.x0,
      x1: b.x1,
      count: b.length,
      y: d3.mean(b, d => d.y)
    }));
  }, [rawData]);
  
  return (
    <ScatterChart>
      <Scatter data={binnedData} />
    </ScatterChart>
  );
}
```

### 5. Disable Animations for Real-time Data

```jsx
function RealtimeChart() {
  const [data, setData] = useState([]);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setData(prev => [...prev.slice(-50), newPoint]);
    }, 100);
    return () => clearInterval(interval);
  }, []);
  
  return (
    <LineChart data={data}>
      <Line 
        type="monotone" 
        dataKey="value" 
        stroke="#8884d8"
        isAnimationActive={false}  // Critical for performance
        dot={false}                // Disable dots
      />
    </LineChart>
  );
}
```

### 6. Optimize Tooltip Performance

```jsx
// BAD: New component reference every render
<Tooltip content={<CustomTooltip />} />

// GOOD: Stable component reference
const CustomTooltip = useMemo(() => {
  return ({ active, payload }) => {
    if (active && payload) {
      return <div>{payload[0].value}</div>;
    }
    return null;
  };
}, []);

<Tooltip content={CustomTooltip} />

// OR use a separate component outside the render function
const StableTooltip = React.memo(({ active, payload }) => {
  if (!active || !payload) return null;
  return <div>{payload[0].value}</div>;
});

<Tooltip content={<StableTooltip />} />
```

### 7. Virtualize Lists with Charts

When rendering many charts in a list:

```jsx
import { useVirtualizer } from '@tanstack/react-virtual';

function ChartList({ datasets }) {
  const parentRef = useRef();
  
  const virtualizer = useVirtualizer({
    count: datasets.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 300,
  });
  
  return (
    <div ref={parentRef} style={{ height: '600px', overflow: 'auto' }}>
      <div style={{ height: `${virtualizer.getTotalSize()}px`, position: 'relative' }}>
        {virtualizer.getVirtualItems().map(virtualItem => (
          <div
            key={virtualItem.key}
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              width: '100%',
              height: `${virtualItem.size}px`,
              transform: `translateY(${virtualItem.start}px)`,
            }}
          >
            <ChartComponent data={datasets[virtualItem.index]} />
          </div>
        ))}
      </div>
    </div>
  );
}
```

## Responsive Design

### 1. Use the `responsive` prop (Recharts 3.3+, recommended)

The `responsive` prop makes charts automatically resize when their container dimensions change. Works with standard CSS sizing, flexbox, and CSS grid:

```jsx
// GOOD: Responsive with CSS sizing
<LineChart data={data} responsive style={{ width: '100%', maxWidth: 800, aspectRatio: '16/9' }}>
  {/* ... */}
</LineChart>

// GOOD: Responsive with explicit dimensions
<LineChart data={data} width="100%" height={300} responsive>
  {/* ... */}
</LineChart>

// BAD: Fixed size - won't adapt to container changes
<LineChart width={600} height={300} data={data}>
  {/* ... */}
</LineChart>
```

### 2. Use ResponsiveContainer (older versions)

For Recharts < 3.3, wrap the chart in `ResponsiveContainer`:

```jsx
<ResponsiveContainer width="100%" height={300}>
  <LineChart data={data}>
    {/* ... */}
  </LineChart>
</ResponsiveContainer>
```

**Important**: `ResponsiveContainer` must have a parent with defined dimensions. Height must be a number, not a percentage.

### 3. Handle Container Sizing

Ensure parent container has defined dimensions (applies to both `responsive` prop and `ResponsiveContainer`):

```jsx
// Parent must have explicit height or flex layout
<div style={{ width: '100%', height: '400px' }}>
  <LineChart data={data} responsive style={{ width: '100%', height: '100%' }}>
    {/* ... */}
  </LineChart>
</div>

// OR using flexbox
<div style={{ display: 'flex', flexDirection: 'column', height: '100vh' }}>
  <div style={{ flex: 1 }}>
    <LineChart data={data} responsive style={{ width: '100%', height: '100%' }}>
      {/* ... */}
    </LineChart>
  </div>
</div>
```

### 3. Adjust for Small Screens

```jsx
import { useMediaQuery } from 'react-responsive';

function AdaptiveChart({ data }) {
  const isMobile = useMediaQuery({ maxWidth: 768 });
  
  return (
    <LineChart data={data} responsive style={{ width: '100%', height: isMobile ? 200 : 400 }}>
      <XAxis 
        dataKey="name" 
        interval={isMobile ? 'preserveEnd' : 0}
        angle={isMobile ? -45 : 0}
        height={isMobile ? 50 : 30}
      />
      <YAxis width={isMobile ? 30 : 60} />
      <Tooltip />
      {/* Reduce chart complexity on mobile */}
      {!isMobile && <Legend />}
      <Line type="monotone" dataKey="value" stroke="#8884d8" />
    </LineChart>
  );
}
```

### 4. Aspect Ratio Preservation

```jsx
<LineChart data={data} responsive style={{ width: '100%', aspectRatio: '16/9' }}>
  {/* ... */}
</LineChart>

{/* Or with ResponsiveContainer (older versions): */}
<ResponsiveContainer width="100%" aspect={16 / 9}>
  <LineChart>{/* ... */}</LineChart>
</ResponsiveContainer>
```

## Accessibility

### 1. Enable Accessibility Layer

Enabled by default, but can be explicitly set:

```jsx
<LineChart accessibilityLayer={true}>
  {/* Components */}
</LineChart>
```

### 2. Add ARIA Labels

```jsx
<LineChart 
  role="img" 
  aria-label="Line chart showing monthly sales from January to June 2024"
>
  {/* Components */}
</LineChart>
```

### 3. Provide Text Alternatives

Always include descriptive text near charts:

```jsx
<figure>
  <LineChart data={data} responsive style={{ width: '100%', height: 300 }}>
    {/* ... */}
  </LineChart>
  <figcaption>
    Sales increased 25% from January to June 2024, 
    with the highest sales in June at $9,800.
  </figcaption>
</figure>
```

### 4. Keyboard Navigation

Charts are keyboard navigable by default when `accessibilityLayer` is enabled (which it is by default). The chart's `tabIndex` prop controls where it appears in the tab order:

```jsx
<LineChart tabIndex={0} accessibilityLayer>
  {/* Components */}
</LineChart>
```

### 5. Color Contrast

Ensure sufficient contrast for all chart elements:

```jsx
<LineChart>
  <Line stroke="#1f77b4" />  // Good contrast on white
  <Line stroke="#ff7f0e" />  // Good contrast on white
  {/* Avoid: stroke="#ddd" on white background */}
</LineChart>
```

### 6. Don't Rely on Color Alone

Use patterns, labels, or different line styles:

```jsx
<LineChart>
  <Line 
    type="monotone" 
    dataKey="sales" 
    stroke="#8884d8" 
    strokeWidth={2}
    name="Sales (solid line)"
  />
  <Line 
    type="monotone" 
    dataKey="profit" 
    stroke="#82ca9d" 
    strokeWidth={2}
    strokeDasharray="5 5"
    name="Profit (dashed line)"
  />
  <Legend />
</LineChart>
```

## Data Patterns

### 1. Data Shape

Recharts expects array of objects:

```javascript
// GOOD
const data = [
  { month: 'Jan', sales: 4000, profit: 2400 },
  { month: 'Feb', sales: 3000, profit: 1398 },
];

// BAD: Array of arrays
const badData = [
  ['Jan', 4000, 2400],
  ['Feb', 3000, 1398],
];

// BAD: Object of arrays
const alsoBad = {
  months: ['Jan', 'Feb'],
  sales: [4000, 3000],
};
```

### 2. Handling Null/Undefined

```jsx
// Data with missing values
const data = [
  { month: 'Jan', sales: 4000 },
  { month: 'Feb', sales: null },  // Missing
  { month: 'Mar', sales: 3000 },
];

// Option 1: Connect through nulls
<Line type="monotone" dataKey="sales" connectNulls={true} />

// Option 2: Gap at null
<Line type="monotone" dataKey="sales" connectNulls={false} />

// Option 3: Pre-process to fill values
const filledData = data.map(item => ({
  ...item,
  sales: item.sales ?? 0  // or interpolate
}));
```

### 3. Data Pre-processing

Transform data before passing to Recharts:

```jsx
const Chart = ({ rawData }) => {
  // Calculate derived values
  const processedData = useMemo(() => {
    return rawData.map(item => ({
      ...item,
      total: item.q1 + item.q2 + item.q3 + item.q4,
      average: (item.q1 + item.q2 + item.q3 + item.q4) / 4,
      growth: ((item.q4 - item.q1) / item.q1) * 100
    }));
  }, [rawData]);
  
  // Filter or sort if needed
  const filteredData = useMemo(() => {
    return processedData
      .filter(item => item.total > 0)
      .sort((a, b) => b.total - a.total);
  }, [processedData]);
  
  return (
    <LineChart data={filteredData}>
      {/* ... */}
    </LineChart>
  );
};
```

### 4. Date/Time Handling

```jsx
import { format, parseISO } from 'date-fns';

const data = [
  { date: '2024-01-01', value: 100 },
  { date: '2024-02-01', value: 150 },
];

// Option 1: Format in data
const formattedData = data.map(d => ({
  ...d,
  formattedDate: format(parseISO(d.date), 'MMM yyyy')
}));

<XAxis dataKey="formattedDate" />

// Option 2: Format with tickFormatter
<XAxis 
  dataKey="date" 
  tickFormatter={(date) => format(parseISO(date), 'MMM')}
/>

// Option 3: Use time scale with custom domain
<XAxis 
  dataKey="date" 
  type="number" 
  scale="time"
  domain={['auto', 'auto']}
  tickFormatter={(timestamp) => format(new Date(timestamp), 'MMM d')}
/>
```

## Visual Design

### 1. Consistent Color Palette

Define a color scheme:

```jsx
const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042', '#8884D8'];

// Use consistently
<Line stroke={COLORS[0]} />
<Line stroke={COLORS[1]} />
<Bar fill={COLORS[0]} />
```

### 2. Typography

```jsx
<XAxis 
  tick={{ fontSize: 12, fontFamily: 'Arial, sans-serif', fill: '#666' }}
  label={{ value: 'Month', fontSize: 14, fontWeight: 'bold', fill: '#333' }}
/>

<YAxis 
  tick={{ fontSize: 12, fill: '#666' }}
  tickFormatter={(value) => `$${value.toLocaleString()}`}
/>
```

### 3. Spacing and Margins

```jsx
<LineChart margin={{ top: 20, right: 30, left: 20, bottom: 20 }}>
  <XAxis dataKey="name" height={60} />
  <YAxis width={80} />
  {/* ... */}
</LineChart>
```

### 4. Grid Styling

```jsx
<CartesianGrid 
  strokeDasharray="3 3" 
  stroke="#e0e0e0"
  vertical={true}
  horizontal={true}
/>
```

### 5. Legends

```jsx
<Legend 
  verticalAlign="top" 
  height={36}
  iconType="circle"
  wrapperStyle={{ paddingTop: 20 }}
/>
```

### 6. Tooltips

```jsx
<Tooltip 
  contentStyle={{ 
    backgroundColor: '#fff', 
    border: '1px solid #ccc',
    borderRadius: '4px',
    padding: '10px',
    boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
  }}
  labelStyle={{ fontWeight: 'bold', marginBottom: '8px' }}
  itemStyle={{ fontSize: '14px' }}
  separator={": "}
/>
```

## Testing and Debugging

### 1. Use Recharts DevTools

Install devtools for debugging:

```bash
npm install @recharts/devtools
```

```jsx
import { RechartsDevtools } from '@recharts/devtools';

<LineChart data={data}>
  {/* ... */}
  <RechartsDevtools />  // Shows hook inspector
</LineChart>
```

### 2. Testing Chart Components

```jsx
import { render, screen } from '@testing-library/react';
import { LineChart, Line, XAxis, YAxis, ResponsiveContainer } from 'recharts';

describe('ChartComponent', () => {
  const mockData = [
    { name: 'A', value: 10 },
    { name: 'B', value: 20 },
  ];
  
  it('renders without crashing', () => {
    render(
      <div style={{ width: '400px', height: '300px' }}>
        <ResponsiveContainer>
          <LineChart data={mockData}>
            <XAxis dataKey="name" />
            <YAxis />
            <Line dataKey="value" />
          </LineChart>
        </ResponsiveContainer>
      </div>
    );
  });
  
  it('displays correct data', () => {
    render(<ChartComponent data={mockData} />);
    // Check for aria-label or figcaption content
    expect(screen.getByLabelText(/sales chart/i)).toBeInTheDocument();
  });
});
```

### 3. Debugging Tips

- Check that parent container has explicit dimensions
- Verify data is array of objects
- Ensure all `dataKey` values exist in data
- Look for console warnings about prop types
- Use React DevTools to inspect re-renders

## Common Pitfalls

### 1. Chart Without Defined Size

```jsx
// WRONG: No dimensions specified
<LineChart data={data}>
  {/* ... */}
</LineChart>

// CORRECT: Use responsive prop with CSS sizing (Recharts 3.3+)
<LineChart data={data} responsive style={{ width: '100%', height: 300 }}>
  {/* ... */}
</LineChart>

// CORRECT: Static pixel dimensions
<LineChart data={data} width={600} height={300}>
  {/* ... */}
</LineChart>

// CORRECT: ResponsiveContainer (older versions) - parent must have defined height
<div style={{ height: '300px' }}>
  <ResponsiveContainer>
    <LineChart data={data}>{/* ... */}</LineChart>
  </ResponsiveContainer>
</div>
```

### 2. Missing dataKey

```jsx
// WRONG
<XAxis />  // No dataKey - won't show labels

// CORRECT
<XAxis dataKey="name" />
```

### 3. Unstable References

```jsx
// WRONG: New array every render
<LineChart data={getData()}>

// CORRECT: Memoized data
const data = useMemo(() => getData(), []);
<LineChart data={data}>
```

### 4. Incorrect Percentage in ResponsiveContainer

```jsx
// WRONG: Height cannot be percentage in ResponsiveContainer
<ResponsiveContainer width="100%" height="100%">

// CORRECT: Height must be number in ResponsiveContainer
<ResponsiveContainer width="100%" height={300}>
// OR use aspect
<ResponsiveContainer width="100%" aspect={2}>

// BETTER (Recharts 3.3+): Use responsive prop — supports CSS percentages
<LineChart data={data} responsive style={{ width: '100%', height: '100%' }}>
```

### 5. Overlapping Labels

```jsx
// Solution: Rotate labels
<XAxis 
  dataKey="name" 
  angle={-45} 
  textAnchor="end" 
  height={80} 
/>

// OR reduce tick count
<XAxis dataKey="name" interval="preserveStartEnd" />
```

### 6. Ignoring Performance Warnings

Always check for:
- Creating new functions in render
- Not memoizing data transformations
- Animating large datasets
- Not using `isAnimationActive={false}` for real-time

## ESLint Configuration

Use eslint-plugin-react-perf to catch performance issues:

```json
{
  "extends": ["plugin:react-perf/recommended"],
  "rules": {
    "react-perf/jsx-no-new-object-as-prop": "warn",
    "react-perf/jsx-no-new-array-as-prop": "warn",
    "react-perf/jsx-no-new-function-as-prop": "warn"
  }
}
```

## Resources

- [Official Performance Guide](https://recharts.github.io/en-US/guide/performance)
- [React.memo Documentation](https://react.dev/reference/react/memo)
- [useMemo Documentation](https://react.dev/reference/react/useMemo)
- [useCallback Documentation](https://react.dev/reference/react/useCallback)
references/examples.md
# Recharts Examples

Common chart patterns and implementation examples.

> **Note**: Examples below use `ResponsiveContainer` for broad compatibility. In Recharts 3.3+, you can use the `responsive` prop instead:
> ```jsx
> <LineChart data={data} responsive style={{ width: '100%', height: 300 }}>
> ```

## Table of Contents

1. [Line Chart Patterns](#line-chart-patterns)
2. [Bar Chart Patterns](#bar-chart-patterns)
3. [Area Chart Patterns](#area-chart-patterns)
4. [Pie Chart Patterns](#pie-chart-patterns)
5. [Scatter Chart Patterns](#scatter-chart-patterns)
6. [Composed Chart Patterns](#composed-chart-patterns)
7. [Advanced Patterns](#advanced-patterns)

## Line Chart Patterns

### Basic Line Chart

```jsx
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';

const data = [
  { month: 'Jan', sales: 4000, profit: 2400 },
  { month: 'Feb', sales: 3000, profit: 1398 },
  { month: 'Mar', sales: 2000, profit: 9800 },
  { month: 'Apr', sales: 2780, profit: 3908 },
  { month: 'May', sales: 1890, profit: 4800 },
  { month: 'Jun', sales: 2390, profit: 3800 },
];

function SimpleLineChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <LineChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Line type="monotone" dataKey="sales" stroke="#8884d8" />
        <Line type="monotone" dataKey="profit" stroke="#82ca9d" />
      </LineChart>
    </ResponsiveContainer>
  );
}
```

### Dashed Line Chart

```jsx
<LineChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Line 
    type="monotone" 
    dataKey="sales" 
    stroke="#8884d8" 
    strokeDasharray="5 5"  // Dashed pattern
  />
</LineChart>
```

### Vertical Line Chart

```jsx
<LineChart layout="vertical" data={data}>
  <XAxis type="number" />
  <YAxis type="category" dataKey="month" />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  <Line type="monotone" dataKey="sales" stroke="#8884d8" />
</LineChart>
```

### Line Chart with Custom Dots

```jsx
const CustomDot = (props) => {
  const { cx, cy, stroke, payload, value } = props;
  
  return (
    <svg x={cx - 10} y={cy - 10} width={20} height={20} fill={stroke} viewBox="0 0 1024 1024">
      <path d="M512 0C229.25 0 0 229.25 0 512s229.25 512 512 512 512-229.25 512-512S794.75 0 512 0z" />
    </svg>
  );
};

<LineChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Line 
    type="monotone" 
    dataKey="sales" 
    stroke="#8884d8"
    dot={<CustomDot />}
    activeDot={{ r: 8 }}
  />
</LineChart>
```

### Synchronized Multi-Chart

```jsx
<>
  <ResponsiveContainer width="100%" height={200}>
    <LineChart data={data} syncId="salesSync">
      <XAxis dataKey="month" />
      <YAxis />
      <CartesianGrid strokeDasharray="3 3" />
      <Tooltip />
      <Line type="monotone" dataKey="sales" stroke="#8884d8" />
    </LineChart>
  </ResponsiveContainer>
  
  <ResponsiveContainer width="100%" height={200}>
    <LineChart data={data} syncId="salesSync">
      <XAxis dataKey="month" />
      <YAxis />
      <CartesianGrid strokeDasharray="3 3" />
      <Tooltip />
      <Line type="monotone" dataKey="profit" stroke="#82ca9d" />
    </LineChart>
  </ResponsiveContainer>
  
  <p>Charts share synchronized tooltips</p>
</>
```

### Highlight and Zoom

```jsx
import { useState } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, Brush } from 'recharts';

function HighlightZoomChart({ data }) {
  const [refAreaLeft, setRefAreaLeft] = useState('');
  const [refAreaRight, setRefAreaRight] = useState('');
  const [zoomData, setZoomData] = useState(data);

  const zoom = () => {
    if (refAreaLeft === refAreaRight || refAreaRight === '') {
      setRefAreaLeft('');
      setRefAreaRight('');
      return;
    }

    // Filter data between selected range
    const left = Math.min(refAreaLeft, refAreaRight);
    const right = Math.max(refAreaLeft, refAreaRight);
    
    const newData = data.filter(
      (d) => d.index >= left && d.index <= right
    );
    
    setZoomData(newData);
    setRefAreaLeft('');
    setRefAreaRight('');
  };

  return (
    <LineChart
      data={zoomData}
      onMouseDown={(e) => e && setRefAreaLeft(e.activeLabel)}
      onMouseMove={(e) => e && refAreaLeft && setRefAreaRight(e.activeLabel)}
      onMouseUp={zoom}
    >
      <CartesianGrid strokeDasharray="3 3" />
      <XAxis dataKey="name" allowDataOverflow />
      <YAxis allowDataOverflow />
      <Tooltip />
      <Line type="monotone" dataKey="value" stroke="#8884d8" />
      
      {refAreaLeft && refAreaRight && (
        <ReferenceArea
          x1={refAreaLeft}
          x2={refAreaRight}
          strokeOpacity={0.3}
        />
      )}
    </LineChart>
  );
}
```

## Bar Chart Patterns

### Basic Bar Chart

```jsx
import { BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer } from 'recharts';

function SimpleBarChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <BarChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Bar dataKey="sales" fill="#8884d8" />
        <Bar dataKey="profit" fill="#82ca9d" />
      </BarChart>
    </ResponsiveContainer>
  );
}
```

### Stacked Bar Chart

```jsx
<BarChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  <Bar dataKey="sales" stackId="a" fill="#8884d8" />
  <Bar dataKey="profit" stackId="a" fill="#82ca9d" />
  <Bar dataKey="expenses" stackId="a" fill="#ffc658" />
</BarChart>
```

### Horizontal Bar Chart

```jsx
<BarChart layout="vertical" data={data}>
  <XAxis type="number" />
  <YAxis type="category" dataKey="month" />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  <Bar dataKey="sales" fill="#8884d8" />
</BarChart>
```

### Grouped Bar Chart

```jsx
<BarChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Legend />
  {/* No stackId = side by side */}
  <Bar dataKey="sales" fill="#8884d8" />
  <Bar dataKey="profit" fill="#82ca9d" />
</BarChart>
```

### Bar Chart with Custom Shape

```jsx
const CustomBarShape = (props) => {
  const { fill, x, y, width, height } = props;
  
  return (
    <g>
      <rect x={x} y={y} width={width} height={height} rx={5} ry={5} fill={fill} />
      <text x={x + width / 2} y={y - 5} textAnchor="middle" fill="#666">
        {props.value}
      </text>
    </g>
  );
};

<BarChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Bar dataKey="sales" fill="#8884d8" shape={<CustomBarShape />} />
</BarChart>
```

### Rounded Corners

```jsx
<BarChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Bar 
    dataKey="sales" 
    fill="#8884d8"
    radius={[4, 4, 0, 0]}  // [topLeft, topRight, bottomRight, bottomLeft]
  />
</BarChart>
```

### Brush-enabled Bar Chart

```jsx
<BarChart data={data}>
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="name" />
  <YAxis />
  <Tooltip />
  <Legend />
  <Bar dataKey="pv" fill="#8884d8" />
  <Bar dataKey="uv" fill="#82ca9d" />
  <Brush dataKey="name" height={30} stroke="#8884d8" />
</BarChart>
```

## Area Chart Patterns

### Basic Area Chart

```jsx
import { AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

function SimpleAreaChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <AreaChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Area type="monotone" dataKey="sales" stroke="#8884d8" fill="#8884d8" />
      </AreaChart>
    </ResponsiveContainer>
  );
}
```

### Area Chart with Gradient

```jsx
<AreaChart data={data}>
  <defs>
    <linearGradient id="colorSales" x1="0" y1="0" x2="0" y2="1">
      <stop offset="5%" stopColor="#8884d8" stopOpacity={0.8}/>
      <stop offset="95%" stopColor="#8884d8" stopOpacity={0}/>
    </linearGradient>
  </defs>
  <XAxis dataKey="month" />
  <YAxis />
  <CartesianGrid strokeDasharray="3 3" />
  <Tooltip />
  <Area 
    type="monotone" 
    dataKey="sales" 
    stroke="#8884d8" 
    fillOpacity={1} 
    fill="url(#colorSales)" 
  />
</AreaChart>
```

### Stacked Area Chart

```jsx
<AreaChart data={data}>
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="month" />
  <YAxis />
  <Tooltip />
  <Legend />
  <Area 
    type="monotone" 
    dataKey="sales" 
    stackId="1" 
    stroke="#8884d8" 
    fill="#8884d8" 
  />
  <Area 
    type="monotone" 
    dataKey="profit" 
    stackId="1" 
    stroke="#82ca9d" 
    fill="#82ca9d" 
  />
</AreaChart>
```

### Percent Area Chart

```jsx
<AreaChart data={data} stackOffset="expand">
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="month" />
  <YAxis tickFormatter={(value) => `${(value * 100).toFixed(0)}%`} />
  <Tooltip formatter={(value) => `${(value * 100).toFixed(0)}%`} />
  <Legend />
  <Area type="monotone" dataKey="sales" stackId="1" stroke="#8884d8" fill="#8884d8" />
  <Area type="monotone" dataKey="profit" stackId="1" stroke="#82ca9d" fill="#82ca9d" />
</AreaChart>
```

## Pie Chart Patterns

### Basic Pie Chart

```jsx
import { PieChart, Pie, Sector, Tooltip, Legend, ResponsiveContainer } from 'recharts';

const data = [
  { name: 'Group A', value: 400 },
  { name: 'Group B', value: 300 },
  { name: 'Group C', value: 300 },
  { name: 'Group D', value: 200 },
];

const COLORS = ['#0088FE', '#00C49F', '#FFBB28', '#FF8042'];

function SimplePieChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <PieChart>
        <Pie
          data={data}
          cx="50%"
          cy="50%"
          labelLine={false}
          label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
          outerRadius={80}
          dataKey="value"
          shape={(props) => <Sector {...props} fill={COLORS[props.index % COLORS.length]} />}
        />
        <Tooltip />
        <Legend />
      </PieChart>
    </ResponsiveContainer>
  );
}
```

### Donut Chart

```jsx
<PieChart>
  <Pie
    data={data}
    cx="50%"
    cy="50%"
    innerRadius={60}
    outerRadius={80}
    paddingAngle={5}
    dataKey="value"
    shape={(props) => <Sector {...props} fill={COLORS[props.index % COLORS.length]} />}
  />
  <Tooltip />
</PieChart>
```

### Two-Level Pie Chart

```jsx
<PieChart>
  <Pie
    data={data01}
    dataKey="value"
    nameKey="name"
    cx="50%"
    cy="50%"
    outerRadius={50}
    fill="#8884d8"
  />
  <Pie
    data={data02}
    dataKey="value"
    nameKey="name"
    cx="50%"
    cy="50%"
    innerRadius={60}
    outerRadius={80}
    fill="#82ca9d"
    label
  />
</PieChart>
```

### Pie Chart with Active Slice

```jsx
import { PieChart, Pie, Sector, Tooltip } from 'recharts';

// Use the `shape` prop with `isActive` to render active/inactive slices differently.
// `activeShape` and `activeIndex` props are deprecated — use `shape` instead.

const renderShape = (props) => {
  const { cx, cy, midAngle, innerRadius, outerRadius, startAngle, endAngle, fill, payload, percent, value, isActive } = props;
  
  if (!isActive) {
    return <Sector {...props} />;
  }
  
  // Expanded active slice with label
  return (
    <g>
      <text x={cx} y={cy} dy={8} textAnchor="middle" fill={fill}>
        {payload.name}
      </text>
      <Sector
        cx={cx}
        cy={cy}
        innerRadius={innerRadius}
        outerRadius={outerRadius}
        startAngle={startAngle}
        endAngle={endAngle}
        fill={fill}
      />
      <Sector
        cx={cx}
        cy={cy}
        startAngle={startAngle}
        endAngle={endAngle}
        innerRadius={outerRadius + 6}
        outerRadius={outerRadius + 10}
        fill={fill}
      />
    </g>
  );
};

function ActivePieChart() {
  return (
    <PieChart width={400} height={400}>
      <Pie
        data={data}
        cx="50%"
        cy="50%"
        innerRadius={60}
        outerRadius={80}
        dataKey="value"
        shape={renderShape}
      />
      <Tooltip defaultIndex={0} />
    </PieChart>
  );
}
```

## Scatter Chart Patterns

### Basic Scatter Chart

```jsx
import { ScatterChart, Scatter, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';

const data = [
  { x: 100, y: 200, z: 200 },
  { x: 120, y: 100, z: 260 },
  { x: 170, y: 300, z: 400 },
  { x: 140, y: 250, z: 280 },
  { x: 150, y: 400, z: 500 },
];

function SimpleScatterChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <ScatterChart>
        <CartesianGrid />
        <XAxis type="number" dataKey="x" name="X" unit="px" />
        <YAxis type="number" dataKey="y" name="Y" unit="px" />
        <Tooltip cursor={{ strokeDasharray: '3 3' }} />
        <Scatter name="Series A" data={data} fill="#8884d8" />
      </ScatterChart>
    </ResponsiveContainer>
  );
}
```

### Bubble Chart

```jsx
<ScatterChart>
  <CartesianGrid />
  <XAxis type="number" dataKey="x" name="X" />
  <YAxis type="number" dataKey="y" name="Y" />
  <ZAxis type="number" dataKey="z" range={[100, 500]} name="Size" />
  <Tooltip cursor={{ strokeDasharray: '3 3' }} />
  <Legend />
  <Scatter name="Group A" data={data01} fill="#8884d8" />
  <Scatter name="Group B" data={data02} fill="#82ca9d" />
</ScatterChart>
```

### Scatter with Trend Line

```jsx
import { LineChart, Line, XAxis, YAxis, Tooltip, ReferenceLine } from 'recharts';

function ScatterWithTrend() {
  // Calculate trend line
  const n = data.length;
  const sumX = data.reduce((sum, d) => sum + d.x, 0);
  const sumY = data.reduce((sum, d) => sum + d.y, 0);
  const sumXY = data.reduce((sum, d) => sum + d.x * d.y, 0);
  const sumX2 = data.reduce((sum, d) => sum + d.x * d.x, 0);
  
  const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);
  const intercept = (sumY - slope * sumX) / n;
  
  const minX = Math.min(...data.map(d => d.x));
  const maxX = Math.max(...data.map(d => d.x));
  
  return (
    <ScatterChart>
      <CartesianGrid />
      <XAxis type="number" dataKey="x" domain={[minX, maxX]} />
      <YAxis type="number" dataKey="y" />
      <Tooltip cursor={{ strokeDasharray: '3 3' }} />
      <Scatter data={data} fill="#8884d8" />
      <ReferenceLine 
        segment={[
          { x: minX, y: slope * minX + intercept },
          { x: maxX, y: slope * maxX + intercept }
        ]} 
        stroke="red" 
        strokeDasharray="3 3" 
      />
    </ScatterChart>
  );
}
```

## Composed Chart Patterns

### Line + Bar + Area

```jsx
import { ComposedChart, Line, Bar, Area, XAxis, YAxis, CartesianGrid, Tooltip, Legend } from 'recharts';

function MixedChart() {
  return (
    <ResponsiveContainer width="100%" height={300}>
      <ComposedChart data={data}>
        <CartesianGrid stroke="#f5f5f5" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Area type="monotone" dataKey="total" fill="#8884d8" stroke="#8884d8" />
        <Bar dataKey="sales" barSize={20} fill="#413ea0" />
        <Line type="monotone" dataKey="profit" stroke="#ff7300" />
      </ComposedChart>
    </ResponsiveContainer>
  );
}
```

### Dual Y-Axis Chart

```jsx
<ComposedChart data={data}>
  <CartesianGrid stroke="#f5f5f5" />
  <XAxis dataKey="name" />
  <YAxis yAxisId="left" />
  <YAxis yAxisId="right" orientation="right" />
  <Tooltip />
  <Legend />
  <Bar yAxisId="left" dataKey="sales" fill="#8884d8" />
  <Line yAxisId="right" type="monotone" dataKey="rate" stroke="#ff7300" />
</ComposedChart>
```

## Advanced Patterns

### Real-time Chart

```jsx
import { useState, useEffect } from 'react';
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip } from 'recharts';

function RealtimeChart() {
  const [data, setData] = useState([]);
  
  useEffect(() => {
    let counter = 0;
    const interval = setInterval(() => {
      setData(prev => {
        const newData = [...prev, {
          time: new Date().toLocaleTimeString(),
          value: Math.floor(Math.random() * 100),
          index: counter++
        }].slice(-20); // Keep last 20 points
        return newData;
      });
    }, 1000);
    
    return () => clearInterval(interval);
  }, []);
  
  return (
    <LineChart data={data}>
      <CartesianGrid strokeDasharray="3 3" />
      <XAxis dataKey="time" interval="preserveStartEnd" />
      <YAxis domain={[0, 100]} />
      <Tooltip />
      <Line 
        type="monotone" 
        dataKey="value" 
        stroke="#8884d8" 
        isAnimationActive={false}  // Disable for performance
        dot={false}
      />
    </LineChart>
  );
}
```

### Chart with Custom Tooltip

```jsx
const CustomTooltip = ({ active, payload, label }) => {
  if (active && payload && payload.length) {
    return (
      <div style={{ 
        backgroundColor: '#fff', 
        padding: '10px', 
        border: '1px solid #ccc',
        borderRadius: '4px',
        boxShadow: '0 2px 4px rgba(0,0,0,0.1)'
      }}>
        <p style={{ margin: 0, fontWeight: 'bold' }}>{label}</p>
        {payload.map((entry, index) => (
          <p key={index} style={{ 
            margin: '5px 0 0 0', 
            color: entry.color,
            fontSize: '14px'
          }}>
            {entry.name}: {entry.value.toLocaleString()}
          </p>
        ))}
      </div>
    );
  }
  return null;
};

<LineChart data={data}>
  <XAxis dataKey="month" />
  <YAxis />
  <Tooltip content={<CustomTooltip />} />
  <Line type="monotone" dataKey="sales" stroke="#8884d8" />
</LineChart>
```

### Chart with Reference Elements

```jsx
<LineChart data={data}>
  <CartesianGrid strokeDasharray="3 3" />
  <XAxis dataKey="month" />
  <YAxis />
  <Tooltip />
  <Legend />
  
  {/* Target line */}
  <ReferenceLine 
    y={5000} 
    label="Target" 
    stroke="red" 
    strokeDasharray="3 3" 
  />
  
  {/* Highlighted period */}
  <ReferenceArea 
    x1="Feb" 
    x2="Apr" 
    label="Campaign" 
    fill="#8884d8" 
    fillOpacity={0.1} 
  />
  
  {/* Important point */}
  <ReferenceDot 
    x="Jun" 
    y={9800} 
    r={8} 
    fill="gold" 
    stroke="orange" 
    label="Peak" 
  />
  
  <Line type="monotone" dataKey="sales" stroke="#8884d8" />
</LineChart>
```

### Treemap

```jsx
import { Treemap, Tooltip } from 'recharts';

const treemapData = [
  { name: 'A', size: 100, children: [
    { name: 'A1', size: 30 },
    { name: 'A2', size: 40 },
    { name: 'A3', size: 30 },
  ]},
  { name: 'B', size: 80, children: [
    { name: 'B1', size: 25 },
    { name: 'B2', size: 55 },
  ]},
];

<Treemap
  width={400}
  height={200}
  data={treemapData}
  dataKey="size"
  stroke="#fff"
  fill="#8884d8"
  content={({ x, y, width, height, index, name, value }) => (
    <g>
      <rect x={x} y={y} width={width} height={height} fill={COLORS[index % COLORS.length]} stroke="#fff" />
      {width > 50 && height > 30 && (
        <text x={x + 10} y={y + 20} fill="#fff" fontSize={12}>
          {name} ({value})
        </text>
      )}
    </g>
  )}
/>
```

### Sankey Diagram

```jsx
import { Sankey } from 'recharts';

const sankeyData = {
  nodes: [
    { name: 'Source A' },
    { name: 'Source B' },
    { name: 'Target X' },
    { name: 'Target Y' },
  ],
  links: [
    { source: 0, target: 2, value: 10 },
    { source: 0, target: 3, value: 5 },
    { source: 1, target: 2, value: 8 },
    { source: 1, target: 3, value: 12 },
  ],
};

<Sankey
  width={400}
  height={300}
  data={sankeyData}
  nodePadding={20}
  nodeWidth={20}
  linkCurvature={0.5}
>
  <Tooltip />
</Sankey>
```

### Radar Chart

```jsx
import { RadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, Radar, Legend } from 'recharts';

const radarData = [
  { subject: 'Math', A: 120, B: 110, fullMark: 150 },
  { subject: 'English', A: 98, B: 130, fullMark: 150 },
  { subject: 'Physics', A: 86, B: 130, fullMark: 150 },
  { subject: 'Chemistry', A: 99, B: 100, fullMark: 150 },
  { subject: 'Biology', A: 85, B: 90, fullMark: 150 },
  { subject: 'History', A: 65, B: 85, fullMark: 150 },
];

<RadarChart cx="50%" cy="50%" outerRadius="80%" data={radarData}>
  <PolarGrid />
  <PolarAngleAxis dataKey="subject" />
  <PolarRadiusAxis angle={30} domain={[0, 150]} />
  <Radar name="Student A" dataKey="A" stroke="#8884d8" fill="#8884d8" fillOpacity={0.6} />
  <Radar name="Student B" dataKey="B" stroke="#82ca9d" fill="#82ca9d" fillOpacity={0.6} />
  <Legend />
  <Tooltip />
</RadarChart>
```

### Custom Axis Tick

```jsx
const CustomTick = ({ x, y, stroke, payload }) => (
  <g transform={`translate(${x},${y})`}>
    <text x={0} y={0} dy={16} textAnchor="end" fill="#666" transform="rotate(-35)">
      {payload.value}
    </text>
  </g>
);

<XAxis dataKey="month" tick={<CustomTick />} height={60} />
```

### Performance-Optimized Large Dataset

```jsx
import { useMemo, useCallback } from 'react';
import { LineChart, Line, XAxis, YAxis, Tooltip } from 'recharts';

function OptimizedChart({ rawData }) {
  // Memoize data processing
  const data = useMemo(() => {
    // Aggregate or sample data if too large
    if (rawData.length > 1000) {
      return rawData.filter((_, i) => i % Math.ceil(rawData.length / 500) === 0);
    }
    return rawData;
  }, [rawData]);
  
  // Stable callback for dataKey if using function
  const dataKey = useCallback((entry) => entry.value, []);
  
  // Memoized tooltip
  const tooltipContent = useMemo(() => <CustomTooltip />, []);
  
  return (
    <LineChart data={data}>
      <XAxis dataKey="time" interval="preserveStartEnd" />
      <YAxis domain={['auto', 'auto']} />
      <Tooltip content={tooltipContent} />
      <Line 
        type="monotone" 
        dataKey={dataKey}
        stroke="#8884d8"
        dot={false}  // Disable dots for performance
        isAnimationActive={false}  // Disable animation
      />
    </LineChart>
  );
}
```