# Next.js Bar Chart

A Next.js bar chart for the App Router: a Chart.js client component rendered from a server component page, in theme colors for light and dark mode.

Use a bar chart to compare values side by side, such as this year's sales against last year's, month by month. In the free and PRO versions of [AdminKit for Next.js](/nextjs/), the `ChartJs` component draws it with Chart.js. AdminKit PRO also has `ApexChart` for ApexCharts.

Chart.js draws on a canvas in the browser, so `ChartJs` is a client component, marked `"use client"`. That decides where the chart goes. The chart's configuration is a function of the theme colors, and pages in the App Router are server components, which cannot pass a function to a client component. So write the chart in its own client component and render that from your page. The page stays a server component with its `metadata` export. [Chart setup](/nextjs/docs/charts/overview/) explains the components.

## Example

Each month has two bars, last year and this year. The rounded top corners (`borderRadius: 10`) come from AdminKit's Chart.js defaults.

```html
<div class="chart">
  <canvas id="chartjs-bar"></canvas>
</div>

<script>
adminkit.chartjs("#chartjs-bar", function (theme) {
  return {
    type: "bar",
    data: {
      labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
      datasets: [{
        label: "Last year",
        backgroundColor: theme.primary,
        borderColor: theme.primary,
        hoverBackgroundColor: theme.primary,
        hoverBorderColor: theme.primary,
        data: [54, 67, 41, 55, 62, 45, 55, 73, 60, 76, 48, 79],
        barPercentage: .75,
        categoryPercentage: .5
      }, {
        label: "This year",
        backgroundColor: "#dee2e6",
        borderColor: "#dee2e6",
        hoverBackgroundColor: "#dee2e6",
        hoverBorderColor: "#dee2e6",
        data: [69, 66, 24, 48, 52, 51, 44, 53, 62, 79, 51, 68],
        barPercentage: .75,
        categoryPercentage: .5
      }]
    },
    options: {
      maintainAspectRatio: false,
      plugins: {
        legend: {
          display: false
        }
      },
      scales: {
        y: {
          grid: {
            display: false
          },
          border: {
            display: false
          },
          stacked: false,
          ticks: {
            stepSize: 20
          }
        },
        x: {
          stacked: false,
          grid: {
            color: "transparent"
          },
          border: {
            display: false
          }
        }
      }
    }
  };
});
</script>
```
```tsx code title="src/components/sales-bar-chart.tsx"
"use client";

import { ChartJs } from "@/components/plugins/chartjs";

export function SalesBarChart() {
  return (
    <div className="chart">
      <ChartJs
        aria-label="Sales per month, last year and this year"
        config={(theme) => ({
          type: "bar",
          data: {
            labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            datasets: [
              {
                label: "Last year",
                backgroundColor: theme.primary,
                borderColor: theme.primary,
                hoverBackgroundColor: theme.primary,
                hoverBorderColor: theme.primary,
                data: [54, 67, 41, 55, 62, 45, 55, 73, 60, 76, 48, 79],
                barPercentage: 0.75,
                categoryPercentage: 0.5,
              },
              {
                label: "This year",
                backgroundColor: "#dee2e6",
                borderColor: "#dee2e6",
                hoverBackgroundColor: "#dee2e6",
                hoverBorderColor: "#dee2e6",
                data: [69, 66, 24, 48, 52, 51, 44, 53, 62, 79, 51, 68],
                barPercentage: 0.75,
                categoryPercentage: 0.5,
              },
            ],
          },
          options: {
            maintainAspectRatio: false,
            plugins: { legend: { display: false } },
            scales: {
              y: {
                grid: { display: false },
                border: { display: false },
                stacked: false,
                ticks: { stepSize: 20 },
              },
              x: {
                stacked: false,
                grid: { color: "transparent" },
                border: { display: false },
              },
            },
          },
        })}
      />
    </div>
  );
}
```

The page imports it like any other component. `pageMetadata()` reads the title and description from `src/data/pages.json`, so a new page needs an entry there (see [Add a page](/nextjs/docs/getting-started/project-structure/#add-a-page)).

```tsx title="src/app/(dashboard)/reports/page.tsx"
import { SalesBarChart } from "@/components/sales-bar-chart";
import { pageMetadata } from "@/lib/site";

export const metadata = pageMetadata("/reports");

export default function ReportsPage() {
  return (
    <>
      <h1 className="h3 mb-3">Reports</h1>
      <div className="card">
        <div className="card-header">
          <h2 className="card-title">Sales</h2>
        </div>
        <div className="card-body">
          <SalesBarChart />
        </div>
      </div>
    </>
  );
}
```

The theme colors are only known in the browser. So the exported HTML has an empty `<canvas>` and a skeleton in the `.chart` box, and the chart draws once the page has hydrated. The server and browser output match, and the layout does not move.

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `config` | `(theme: Theme) => ChartConfiguration` | | The Chart.js configuration: `type`, `data` and `options`. Called again with the new colors when the color mode changes |

Other props, such as `id` and `aria-label`, go to the `<canvas>`. The container heights and AdminKit's Chart.js defaults are on [Chart setup](/nextjs/docs/charts/overview/#chartjs).

## Colors in dark mode

To make a color follow the mode, read it from `theme`. "This year" keeps the fixed `#dee2e6` of the HTML example, so it stays light gray in dark mode. `theme["gray-300"]` gives the same gray in light mode and follows the gray scale of dark mode:

```tsx
backgroundColor: theme["gray-300"],
```

## Horizontal and stacked bars

Horizontal and stacked bars are a matter of Chart.js options. `indexAxis: "y"` turns the bars sideways, and `stacked: true` on both scales stacks the series:

```tsx
options: {
  indexAxis: "y",
  scales: {
    x: { stacked: true },
    y: { stacked: true },
  },
},
```

## ApexCharts example

> This example is only available in **AdminKit PRO**. [Learn more](/pricing/#nextjs).

This example draws a horizontal stacked bar chart with `ApexChart`. `plotOptions.bar.horizontal` lays the bars on their side, and `chart.stacked` stacks the series. `ApexChart` is a client component too, so this file also starts with `"use client"`. It loads ApexCharts in the browser only, so you don't need `next/dynamic`.

```html
<div id="apexcharts-bar"></div>

<script>
var options = {
  chart: {
    height: 350,
    type: "bar",
    stacked: true,
  },
  plotOptions: {
    bar: {
      horizontal: true,
    },
  },
  stroke: {
    width: 1,
    colors: ["#fff"]
  },
  series: [{
    name: "Marine Sprite",
    data: [44, 55, 41, 37, 22, 43, 21]
  }, {
    name: "Striking Calf",
    data: [53, 32, 33, 52, 13, 43, 32]
  }, {
    name: "Tank Picture",
    data: [12, 17, 11, 9, 15, 11, 20]
  }, {
    name: "Bucket Slope",
    data: [9, 7, 5, 8, 6, 9, 4]
  }, {
    name: "Reborn Kid",
    data: [25, 12, 19, 32, 25, 24, 10]
  }],
  xaxis: {
    categories: [2020, 2021, 2022, 2023, 2024, 2025, 2026],
    labels: {
      formatter: function(val) {
        return val + "K"
      }
    }
  },
  yaxis: {
    title: {
      text: undefined
    },
  },
  tooltip: {
    y: {
      formatter: function(val) {
        return val + "K"
      }
    }
  },
  fill: {
    opacity: 1
  },
  legend: {
    position: "top",
    horizontalAlign: "left",
    offsetX: 40
  }
}
adminkit.apexcharts("#apexcharts-bar", function () {
  return options;
});
</script>
```
```tsx code title="src/components/products-bar-chart.tsx"
"use client";

import { ApexChart } from "@/components/plugins/apexcharts";

export function ProductsBarChart() {
  return (
    <div className="position-relative" style={{ minHeight: 365 }}>
      <ApexChart
        options={() => ({
          chart: { height: 350, type: "bar", stacked: true },
          plotOptions: { bar: { horizontal: true } },
          stroke: { width: 1, colors: ["#fff"] },
          series: [
            { name: "Marine Sprite", data: [44, 55, 41, 37, 22, 43, 21] },
            { name: "Striking Calf", data: [53, 32, 33, 52, 13, 43, 32] },
            { name: "Tank Picture", data: [12, 17, 11, 9, 15, 11, 20] },
            { name: "Bucket Slope", data: [9, 7, 5, 8, 6, 9, 4] },
            { name: "Reborn Kid", data: [25, 12, 19, 32, 25, 24, 10] },
          ],
          xaxis: {
            categories: [2020, 2021, 2022, 2023, 2024, 2025, 2026],
            labels: { formatter: (val: string) => val + "K" },
          },
          yaxis: { title: { text: undefined } },
          tooltip: { y: { formatter: (val: number) => val + "K" } },
          fill: { opacity: 1 },
          legend: { position: "top", horizontalAlign: "left", offsetX: 40 },
        })}
      />
    </div>
  );
}
```

Without `colors` in the options, the series take the primary, success, warning, danger and info colors of the current mode. The 1px `#fff` stroke between the stacked parts stays white in dark mode. `theme.white`, the surface color, follows the mode.

## Accessibility

- The `<canvas>` that `ChartJs` renders has `role="img"`. Screen readers do not read the bars, so give it an `aria-label` that says what it shows, and the figures that matter in text.
- The legend is hidden in the Chart.js example, so the two series differ only by color. Name them in the card text or turn the legend on.
- Under `prefers-reduced-motion`, both components draw the chart without the entrance animation.

## Related

- [React bar chart](/react/docs/charts/bar-chart/): the same chart in AdminKit for React (Vite)
- [Bootstrap 5 bar chart](/bootstrap/docs/charts/bar-chart/): the bar chart of the HTML version
- [Chart setup](/nextjs/docs/charts/overview/): the `ChartJs`, `ApexChart` and `VectorMap` components
- [Line chart](/nextjs/docs/charts/line-chart/): values over time
- [Chart.js demo](https://nextjs-demo.adminkit.io/charts-chartjs) and [ApexCharts demo](https://nextjs-demo.adminkit.io/charts-apexcharts)

---

Canonical HTML page: https://adminkit.io/nextjs/docs/charts/bar-chart/

Site overview for agents: https://adminkit.io/llms.txt (expanded: https://adminkit.io/llms-full.txt) · Documentation: https://adminkit.io/bootstrap/docs/ · Questions: support@adminkit.io
