Claude Code for Recharts: Composable Charts in React — Claude Skills 360 Blog
Blog / Frontend / Claude Code for Recharts: Composable Charts in React
Frontend

Claude Code for Recharts: Composable Charts in React

Published: March 13, 2027
Read time: 7 min read
By: Claude Skills 360

Recharts builds charts from composable React components — LineChart wraps Line, XAxis, YAxis, CartesianGrid, and Tooltip as children. ResponsiveContainer makes charts fluid within their parent. Custom tooltips receive the payload prop with all data for the hovered point. AreaChart with LinearGradient fills areas. Stacked BarChart renders series with stackId="stack". Reference lines mark thresholds; reference areas highlight date ranges. Recharts is SVG-based and renders server-side for static screenshots. The syncId prop synchronizes hover state across multiple charts. Real-time charts add new data to state arrays and trim to a fixed window. Claude Code generates Recharts chart configurations, custom tooltip components, multi-series visualizations, and the real-time data update patterns for analytics dashboards.

CLAUDE.md for Recharts

## Recharts Stack
- Version: recharts >= 2.12
- Container: <ResponsiveContainer width="100%" height={300}> — fluid sizing
- Line: <LineChart data={data}><Line dataKey="value" stroke="#3b82f6" /></LineChart>
- Bar: <BarChart data={data}><Bar dataKey="revenue" stackId="stack" /></BarChart>
- Area: <AreaChart> with <defs><LinearGradient> for fill
- Tooltip: <Tooltip content={<CustomTooltip />}> — payload has { name, value, color }
- Axis: <XAxis dataKey="date" tickFormatter={formatDate} /> <YAxis tickFormatter={formatCurrency} />
- Responsive: wrap in <ResponsiveContainer> for fluid width

Revenue Line Chart

// components/charts/RevenueChart.tsx — line chart with custom tooltip
"use client"
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
  ReferenceLine,
} from "recharts"

interface RevenueData {
  date: string
  revenue: number
  orders: number
  target?: number
}

interface CustomTooltipProps {
  active?: boolean
  payload?: Array<{ name: string; value: number; color: string }>
  label?: string
}

function CustomTooltip({ active, payload, label }: CustomTooltipProps) {
  if (!active || !payload?.length) return null

  return (
    <div className="rounded-lg border bg-background p-3 shadow-lg text-sm">
      <p className="font-semibold text-foreground mb-2">{label}</p>
      {payload.map(entry => (
        <div key={entry.name} className="flex items-center gap-2">
          <div className="h-2 w-2 rounded-full" style={{ backgroundColor: entry.color }} />
          <span className="text-muted-foreground">{entry.name}:</span>
          <span className="font-medium">
            {entry.name === "revenue"
              ? `$${(entry.value / 100).toLocaleString()}`
              : entry.value.toLocaleString()}
          </span>
        </div>
      ))}
    </div>
  )
}

export function RevenueChart({ data }: { data: RevenueData[] }) {
  const avgRevenue = data.reduce((sum, d) => sum + d.revenue, 0) / data.length

  return (
    <ResponsiveContainer width="100%" height={320}>
      <LineChart data={data} margin={{ top: 5, right: 20, left: 0, bottom: 5 }}>
        <defs>
          <filter id="glow">
            <feGaussianBlur stdDeviation="3" result="coloredBlur" />
            <feMerge>
              <feMergeNode in="coloredBlur" />
              <feMergeNode in="SourceGraphic" />
            </feMerge>
          </filter>
        </defs>

        <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />

        <XAxis
          dataKey="date"
          tickLine={false}
          axisLine={false}
          tick={{ fill: "hsl(var(--muted-foreground))", fontSize: 12 }}
          tickFormatter={date => new Date(date).toLocaleDateString("en", { month: "short", day: "numeric" })}
        />

        <YAxis
          tickLine={false}
          axisLine={false}
          tick={{ fill: "hsl(var(--muted-foreground))", fontSize: 12 }}
          tickFormatter={v => `$${(v / 100 / 1000).toFixed(0)}k`}
          width={48}
        />

        <Tooltip content={<CustomTooltip />} />
        <Legend wrapperStyle={{ paddingTop: "16px" }} />

        <ReferenceLine
          y={avgRevenue}
          stroke="hsl(var(--muted-foreground))"
          strokeDasharray="4 4"
          label={{ value: "Avg", fontSize: 11, fill: "hsl(var(--muted-foreground))" }}
        />

        <Line
          type="monotone"
          dataKey="revenue"
          stroke="#3b82f6"
          strokeWidth={2}
          dot={false}
          activeDot={{ r: 4, strokeWidth: 0 }}
          filter="url(#glow)"
        />

        <Line
          type="monotone"
          dataKey="target"
          stroke="#10b981"
          strokeWidth={1.5}
          strokeDasharray="4 4"
          dot={false}
        />
      </LineChart>
    </ResponsiveContainer>
  )
}

Stacked Bar Chart

// components/charts/OrdersBarChart.tsx — stacked bar by status
import {
  BarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, Legend, ResponsiveContainer,
} from "recharts"

interface OrdersData {
  week: string
  pending: number
  processing: number
  shipped: number
  delivered: number
}

const STATUS_COLORS = {
  pending: "#f59e0b",
  processing: "#3b82f6",
  shipped: "#8b5cf6",
  delivered: "#10b981",
}

export function OrdersBarChart({ data }: { data: OrdersData[] }) {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <BarChart data={data} barSize={28} maxBarSize={40}>
        <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" vertical={false} />
        <XAxis
          dataKey="week"
          tickLine={false}
          axisLine={false}
          tick={{ fontSize: 12, fill: "hsl(var(--muted-foreground))" }}
        />
        <YAxis hide />
        <Tooltip
          cursor={{ fill: "hsl(var(--muted) / 0.5)" }}
          content={({ active, payload, label }) => {
            if (!active || !payload?.length) return null
            const total = payload.reduce((sum, p) => sum + (p.value as number), 0)
            return (
              <div className="rounded-lg border bg-background p-3 shadow-lg text-sm space-y-1">
                <p className="font-semibold">{label} — {total} orders</p>
                {payload.map(entry => (
                  <div key={entry.name} className="flex justify-between gap-4">
                    <span className="text-muted-foreground">{entry.name}</span>
                    <span>{entry.value}</span>
                  </div>
                ))}
              </div>
            )
          }}
        />
        <Legend />
        {(["pending", "processing", "shipped", "delivered"] as const).map(status => (
          <Bar
            key={status}
            dataKey={status}
            stackId="orders"
            fill={STATUS_COLORS[status]}
            radius={status === "delivered" ? [4, 4, 0, 0] : [0, 0, 0, 0]}
          />
        ))}
      </BarChart>
    </ResponsiveContainer>
  )
}

Area Chart with Gradient

// components/charts/ConversionAreaChart.tsx
import {
  AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
} from "recharts"

export function ConversionAreaChart({ data }: { data: { date: string; rate: number }[] }) {
  return (
    <ResponsiveContainer width="100%" height={200}>
      <AreaChart data={data}>
        <defs>
          <linearGradient id="conversionGradient" x1="0" y1="0" x2="0" y2="1">
            <stop offset="5%" stopColor="#3b82f6" stopOpacity={0.3} />
            <stop offset="95%" stopColor="#3b82f6" stopOpacity={0} />
          </linearGradient>
        </defs>
        <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
        <XAxis dataKey="date" tick={{ fontSize: 11 }} tickLine={false} axisLine={false} />
        <YAxis tickFormatter={v => `${v}%`} tick={{ fontSize: 11 }} tickLine={false} axisLine={false} width={36} />
        <Tooltip
          formatter={(value: number) => [`${value.toFixed(1)}%`, "Conversion Rate"]}
          labelFormatter={label => new Date(label).toLocaleDateString()}
        />
        <Area
          type="monotone"
          dataKey="rate"
          stroke="#3b82f6"
          strokeWidth={2}
          fill="url(#conversionGradient)"
          dot={false}
        />
      </AreaChart>
    </ResponsiveContainer>
  )
}

Real-Time Rolling Chart

// components/charts/RealtimeMetricsChart.tsx
"use client"
import { useEffect, useRef, useState } from "react"
import { LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid } from "recharts"

const WINDOW_SIZE = 60  // Keep last 60 data points

interface MetricPoint {
  time: string
  latency: number
  errorRate: number
}

export function RealtimeMetricsChart({ metricSource }: { metricSource: () => Promise<{ latency: number; errorRate: number }> }) {
  const [data, setData] = useState<MetricPoint[]>([])
  const intervalRef = useRef<ReturnType<typeof setInterval>>()

  useEffect(() => {
    intervalRef.current = setInterval(async () => {
      const metrics = await metricSource()
      const point: MetricPoint = {
        time: new Date().toLocaleTimeString(),
        latency: metrics.latency,
        errorRate: metrics.errorRate,
      }

      setData(prev => [...prev.slice(-(WINDOW_SIZE - 1)), point])
    }, 1000)

    return () => clearInterval(intervalRef.current)
  }, [metricSource])

  return (
    <ResponsiveContainer width="100%" height={200}>
      <LineChart data={data} isAnimationActive={false}>
        <CartesianGrid strokeDasharray="3 3" stroke="hsl(var(--border))" />
        <XAxis dataKey="time" tick={false} />
        <YAxis yAxisId="latency" orientation="left" tickFormatter={v => `${v}ms`} tick={{ fontSize: 11 }} width={44} />
        <YAxis yAxisId="errorRate" orientation="right" tickFormatter={v => `${v}%`} tick={{ fontSize: 11 }} width={36} />
        <Tooltip />
        <Line yAxisId="latency" type="monotone" dataKey="latency" stroke="#3b82f6" dot={false} strokeWidth={1.5} />
        <Line yAxisId="errorRate" type="monotone" dataKey="errorRate" stroke="#ef4444" dot={false} strokeWidth={1.5} />
      </LineChart>
    </ResponsiveContainer>
  )
}

For the Tremor UI alternative that wraps Recharts with pre-styled components (AreaChart, BarChart, DonutChart) designed for dashboards — less flexible but faster to set up with consistent styling, see the dashboard component patterns. For the Victory charting library alternative that provides a similar React component API with more animated transitions and React Native support through victory-native for cross-platform chart components, the data visualization guide covers Victory setup. The Claude Skills 360 bundle includes Recharts skill sets covering line/bar/area charts, custom tooltips, and real-time updates. Start with the free tier to try Recharts configuration generation.

Keep Reading

Frontend

Claude Code for Chart.js Advanced: Custom Plugins and Mixed Charts

Advanced Chart.js patterns with Claude Code — chart.register() for tree-shaking, mixed chart types combining bar and line, custom plugin API with beforeDraw and afterDatasetsDraw hooks, ScriptableContext for computed colors, ChartDataLabels plugin for value labels, chartjs-plugin-zoom for pan and zoom, custom gradient fills via ctx.createLinearGradient, ChartJS annotation plugin for threshold lines, streaming data with chartjs-plugin-streaming, and react-chartjs-2 with useRef and chart instance.

6 min read Jun 27, 2027
Frontend

Claude Code for Nivo: Rich SVG and Canvas Charts

Build rich data visualizations with Nivo and Claude Code — ResponsiveLine and ResponsiveBar for adaptive charts, ResponsiveHeatMap for matrix data, ResponsiveTreeMap for hierarchal data, ResponsiveSunburst for nested proportions, ResponsiveChord for relationship diagrams, ResponsiveCalendar for activity heat maps, ResponsiveNetwork for force graphs, NivoTheme for consistent styling, tooltip customization with sliceTooltip, and motion config for spring animations.

6 min read Jun 26, 2027
Frontend

Claude Code for Victory Charts: React Native and Web Charts

Build cross-platform charts with Victory and Claude Code — VictoryChart, VictoryLine, VictoryBar, and VictoryScatter for web and React Native, VictoryPie for donut charts, VictoryArea for stacked areas, VictoryAxis for custom axes, VictoryTooltip and VictoryVoronoiContainer for hover tooltips, VictoryBrushContainer for range selection, VictoryZoomContainer for pan and zoom, VictoryLegend for series labels, custom theme with VictoryTheme, and VictoryStack for grouped bars.

6 min read Jun 25, 2027

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free