# Bar Chart

Bars side by side or stacked, for comparing amounts across categories.

Source: [bar-chart.tsx](https://github.com/jakejarvis/jarvis-ui/blob/main/src/components/ui/bar-chart.tsx)

```tsx
import { BarChart, BarChartSeries } from "@/components/ui/bar-chart";
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
import {
  ChartGrid,
  ChartLegend,
  ChartTooltip,
  ChartXAxis,
  ChartYAxis,
  type ChartConfig,
} from "@/components/ui/chart";

const data = [
  { month: "January", subscriptions: 4200, services: 1800 },
  { month: "February", subscriptions: 4650, services: 1500 },
  { month: "March", subscriptions: 5100, services: 2300 },
  { month: "April", subscriptions: 4980, services: 2100 },
  { month: "May", subscriptions: 5620, services: 2600 },
  { month: "June", subscriptions: 6040, services: 2450 },
];

const config = {
  subscriptions: { label: "Subscriptions" },
  services: { label: "Services" },
} satisfies ChartConfig;

export default function BarChartRevenue() {
  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle>Revenue</CardTitle>
        <CardDescription>January to June 2026</CardDescription>
      </CardHeader>
      <CardContent>
        <BarChart data={data} config={config} className="aspect-[4/3] sm:aspect-[2/1]">
          <ChartGrid />
          <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
          <ChartYAxis tickFormatter={(amount: number) => (amount ? `$${amount / 1000}k` : "$0")} />
          <ChartTooltip valueFormatter={(amount) => `$${amount.toLocaleString("en-US")}`} />
          <ChartLegend />
          <BarChartSeries dataKey="subscriptions" />
          <BarChartSeries dataKey="services" />
        </BarChart>
      </CardContent>
    </Card>
  );
}
```

## Installation

Add the registry, once per project:

```bash
npx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json
```

Then add the component:

```bash
npx shadcn@latest add @jarvis/bar-chart
```

## Usage

```tsx
import { BarChart, BarChartSeries } from "@/components/ui/bar-chart";
import { ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";

const data = [
  { month: "January", visitors: 186 },
  { month: "February", visitors: 305 },
  { month: "March", visitors: 237 },
];

const config = {
  visitors: { label: "Visitors" },
} satisfies ChartConfig;

export function VisitorsChart() {
  return (
    <BarChart data={data} config={config}>
      <ChartXAxis dataKey="month" />
      <ChartTooltip />
      <BarChartSeries dataKey="visitors" />
    </BarChart>
  );
}
```

`BarChartSeries` draws one series. The axes, tooltip, legend and config come from
[Chart](https://ui.jarv.is/components/chart.md).

## Composition

- `BarChart`
  - [`ChartGrid`](https://ui.jarv.is/components/chart.md)
  - [`ChartXAxis`](https://ui.jarv.is/components/chart.md)
  - [`ChartYAxis`](https://ui.jarv.is/components/chart.md)
  - [`ChartTooltip`](https://ui.jarv.is/components/chart.md)
  - [`ChartLegend`](https://ui.jarv.is/components/chart.md)
  - `BarChartSeries`

## Examples

### Stacked

`stack="stacked"` stacks the series in the order they're written. `stack="expanded"` stretches
each stack to the same height to compare shares.

```tsx
import { BarChart, BarChartSeries } from "@/components/ui/bar-chart";
import { ChartLegend, ChartTooltip, ChartXAxis, type ChartConfig } from "@/components/ui/chart";

const data = [
  { month: "January", subscriptions: 4200, services: 1800 },
  { month: "February", subscriptions: 4650, services: 1500 },
  { month: "March", subscriptions: 5100, services: 2300 },
  { month: "April", subscriptions: 4980, services: 2100 },
  { month: "May", subscriptions: 5620, services: 2600 },
  { month: "June", subscriptions: 6040, services: 2450 },
];

const config = {
  subscriptions: { label: "Subscriptions" },
  services: { label: "Services" },
} satisfies ChartConfig;

export default function BarChartStacked() {
  return (
    <BarChart data={data} config={config} stack="stacked" className="max-w-lg">
      <ChartXAxis dataKey="month" tickFormatter={(month: string) => month.slice(0, 3)} />
      <ChartTooltip valueFormatter={(amount) => `$${amount.toLocaleString("en-US")}`} />
      <ChartLegend />
      <BarChartSeries dataKey="subscriptions" />
      <BarChartSeries dataKey="services" />
    </BarChart>
  );
}
```

### Horizontal

`orientation="horizontal"` puts the categories on the y-axis.

```tsx
import { BarChart, BarChartSeries } from "@/components/ui/bar-chart";
import { ChartTooltip, ChartXAxis, ChartYAxis, type ChartConfig } from "@/components/ui/chart";

const data = [
  { page: "/", views: 12840 },
  { page: "/pricing", views: 7310 },
  { page: "/docs", views: 6120 },
  { page: "/blog", views: 3480 },
  { page: "/changelog", views: 1950 },
];

const config = {
  views: { label: "Views" },
} satisfies ChartConfig;

export default function BarChartHorizontal() {
  return (
    <BarChart data={data} config={config} orientation="horizontal" className="max-w-lg">
      <ChartXAxis type="number" hide />
      <ChartYAxis dataKey="page" type="category" />
      <ChartTooltip />
      <BarChartSeries dataKey="views" />
    </BarChart>
  );
}
```

### Projected

A hatched series reads as an estimate, here stacked with the actual figures.

```tsx
import { BarChart, BarChartSeries } from "@/components/ui/bar-chart";
import {
  ChartGrid,
  ChartLegend,
  ChartTooltip,
  ChartXAxis,
  type ChartConfig,
} from "@/components/ui/chart";

const data = [
  { quarter: "Q1", actual: 182 },
  { quarter: "Q2", actual: 214 },
  { quarter: "Q3", actual: 238 },
  { quarter: "Q4", projected: 266 },
];

const config = {
  actual: { label: "Actual" },
  projected: { label: "Projected", color: "var(--chart-1)" },
} satisfies ChartConfig;

export default function BarChartProjected() {
  return (
    <BarChart data={data} config={config} stack="stacked" className="max-w-lg">
      <ChartGrid />
      <ChartXAxis dataKey="quarter" />
      <ChartTooltip />
      <ChartLegend />
      <BarChartSeries dataKey="actual" />
      <BarChartSeries dataKey="projected" variant="hatched" />
    </BarChart>
  );
}
```

## Props

| Part | Extends |
| --- | --- |
| `BarChart` | [`Chart`](https://ui.jarv.is/components/chart.md) |
| `BarChartSeries` | `Bar` |

### BarChart

| Prop           | Type                                | Description                                                                                                                                                                                                 |
| -------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `config`       | `ChartConfig`                       | Each series' label, icon and color, keyed by its data key.                                                                                                                                                  |
| `data`         | `Record<string, unknown>[]`         | The rows to plot, one object per category.                                                                                                                                                                  |
| `orientation?` | `"horizontal" \| "vertical"`        | Which way the bars run: up from the x-axis, or across from the y-axis. Horizontal bars take their categories on the y-axis, so give `ChartYAxis` the `dataKey` and `type="category"`. Default: `"vertical"` |
| `stack?`       | `"expanded" \| "none" \| "stacked"` | How the series combine: side by side, stacked, or stacked and scaled to the same length, so each shows its share. Default: `"none"`                                                                         |
| `children?`    | `React.ReactNode`                   |                                                                                                                                                                                                             |

### BarChartSeries

| Prop       | Type                   | Description                                                                                  |
| ---------- | ---------------------- | -------------------------------------------------------------------------------------------- |
| `dataKey`  | `string`               | The key of the series' values in each row, which also names it in the config.                |
| `variant?` | `"hatched" \| "solid"` | How the bars are filled. Hatched bars suit estimates and forecasts. Default: `"solid"`       |
| `radius?`  | `number`               | The radius of the bars' outer corners, or of every corner when they're stacked. Default: `2` |

`BarChartSeries` takes the props of Recharts' [`Bar`](https://recharts.github.io/en-US/api/Bar/)
too, such as `maxBarSize`.
