Shadcn Combo Chart (Bar + Line)

Mix bars and lines in a single shadcn/ui chart. Pick per series whether it renders as a bar or a line, which suits actuals-vs-target and volume-vs-rate views.

CSV, TSV from Excel/Sheets, a Markdown table, or JSON.

CSV
Series
Revenue
Target
Code
+64%Growth
Revenue359K
Target345K
Image
chart.tsx
"use client"

import { useId } from "react"
import { Bar, CartesianGrid, ComposedChart, Line, Rectangle, XAxis, YAxis } from "recharts"
import {
  type ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from "@/components/ui/chart"

const data = [
  { Month: "Jan", Revenue: 42000, Target: 45000 },
  { Month: "Feb", Revenue: 58000, Target: 50000 },
  { Month: "Mar", Revenue: 51000, Target: 55000 },
  { Month: "Apr", Revenue: 67000, Target: 60000 },
  { Month: "May", Revenue: 72000, Target: 65000 },
  { Month: "Jun", Revenue: 69000, Target: 70000 },
]

const chartConfig = {
  Revenue: { label: "Revenue", color: "var(--chart-1)" },
  Target: { label: "Target", color: "var(--chart-2)" },
} satisfies ChartConfig

export function Chart() {
  const uid = useId().replace(/[^\w-]/g, "")

  return (
    <ChartContainer config={chartConfig} className="aspect-auto h-[350px] w-full">
      <ComposedChart accessibilityLayer data={data}>
        <defs>
          <linearGradient id={`${uid}-fill-0`} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="var(--color-Revenue)" stopOpacity={1} />
            <stop offset="100%" stopColor="var(--color-Revenue)" stopOpacity={0.55} />
          </linearGradient>
          <linearGradient id={`${uid}-fill-1`} x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopColor="var(--color-Target)" stopOpacity={1} />
            <stop offset="100%" stopColor="var(--color-Target)" stopOpacity={0.55} />
          </linearGradient>
        </defs>
        <CartesianGrid vertical={false} strokeDasharray="3 5" />
        <XAxis dataKey="Month" tickLine={false} axisLine={false} tickMargin={10} />
        <YAxis tickLine={false} axisLine={false} tickMargin={8} width={40} tickFormatter={(value) => new Intl.NumberFormat("en-US", { notation: "compact", maximumFractionDigits: 1 }).format(value)} />
        <ChartTooltip cursor={{ fill: "var(--muted)", opacity: 0.6 }} content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} itemSorter={null} />
        <Bar dataKey="Revenue" fill="var(--color-Revenue)" shape={(props) => <Rectangle {...props} fill={`url(#${uid}-fill-0)`} />} radius={[6, 6, 0, 0]} maxBarSize={36} />
        <Line dataKey="Target" type="monotone" stroke="var(--color-Target)" strokeWidth={2.5} dot={{ r: 3, fill: "var(--card)", strokeWidth: 2 }} activeDot={{ r: 5, strokeWidth: 2, stroke: "var(--card)" }} />
      </ComposedChart>
    </ChartContainer>
  )
}

When to use a combo chart

Combo charts put two related measures in one view without making them compete.

  • Revenue (bars) vs. target (line)
  • Orders (bars) with a moving average (line)
  • Spend (bars) with conversions (line)

Data format

  • By default the first series renders as bars and the rest as lines.
  • Paste CSV, JSON from your API, TSV copied from Excel or Google Sheets, or a Markdown table. The generated component keeps your column names as its data keys.
CSV
Month,Revenue,Target
Jan,42000,45000
Feb,58000,50000
Mar,51000,55000
Apr,67000,60000
May,72000,65000
Jun,69000,70000
Same data as JSON
[
  {"month": "Jan", "revenue": 42000, "target": 45000},
  {"month": "Feb", "revenue": 58000, "target": 50000},
  {"month": "Mar", "revenue": 51000, "target": 55000},
  …
]

Options

Series type
Switch any series between Bar and Line.
Colors
Custom color per series.

How to add it to your project

  1. 1. Add the shadcn/ui chart component (it installs Recharts):
    npx shadcn@latest add chart
  2. 2. Paste your data above, pick the options, and copy the generated chart.tsx.
  3. 3. Save it in your project (e.g. components/combo-chart.tsx) and render <Chart />, or <Chart data={rows} /> in Data as prop mode.

Combo Chart FAQ