# Next.js Doughnut Chart

Build a Next.js doughnut chart with Chart.js: a client component with a 65% cutout, rendered from a server component page in the App Router.

A doughnut chart shows a total split into a few parts as a ring: a pie chart with an empty center. In the free and PRO versions of [AdminKit for Next.js](/nextjs/), the `ChartJs` component draws it with Chart.js. In AdminKit PRO, `ApexChart` draws the ApexCharts version.

`ChartJs` is a client component, since Chart.js draws in the browser. You describe the chart with a function of the theme colors. Pages in the App Router are server components, and server components cannot pass functions to client components. So the chart lives in its own `"use client"` file that your page renders. More in [Chart setup](/nextjs/docs/charts/overview/).

## Example

Traffic sources with a cutout of 65% of the radius.

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

<script>
adminkit.chartjs("#chartjs-doughnut", function (theme) {
  return {
    type: "doughnut",
    data: {
      labels: ["Social", "Search Engines", "Direct", "Other"],
      datasets: [{
        data: [260, 125, 54, 146],
        backgroundColor: [
          theme.primary,
          theme.success,
          theme.warning,
          "#dee2e6"
        ],
        borderColor: "transparent"
      }]
    },
    options: {
      maintainAspectRatio: false,
      cutout: "65%",
      plugins: {
        legend: {
          display: false
        }
      }
    }
  };
});
</script>
```
```tsx code title="src/components/traffic-doughnut-chart.tsx"
"use client";

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

export function TrafficDoughnutChart() {
  return (
    <div className="chart">
      <ChartJs
        aria-label="Visits per traffic source"
        config={(theme) => ({
          type: "doughnut",
          data: {
            labels: ["Social", "Search Engines", "Direct", "Other"],
            datasets: [
              {
                data: [260, 125, 54, 146],
                backgroundColor: [theme.primary, theme.success, theme.warning, "#dee2e6"],
                borderColor: "transparent",
              },
            ],
          },
          options: {
            maintainAspectRatio: false,
            cutout: "65%",
            plugins: { legend: { display: false } },
          },
        })}
      />
    </div>
  );
}
```

The server component page renders it:

```tsx title="src/app/(dashboard)/traffic/page.tsx"
import { TrafficDoughnutChart } from "@/components/traffic-doughnut-chart";
import { pageMetadata } from "@/lib/site";

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

export default function TrafficPage() {
  return (
    <>
      <h1 className="h3 mb-3">Traffic</h1>
      <div className="card">
        <div className="card-header">
          <h2 className="card-title">Traffic sources</h2>
        </div>
        <div className="card-body">
          <TrafficDoughnutChart />
        </div>
      </div>
    </>
  );
}
```

The exported HTML shows a skeleton where the chart goes. The ring draws once the browser has taken over that HTML (hydration).

## Props

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

Other props, such as `id` and `aria-label`, go to the `<canvas>`. The demo's doughnut chart sits in `.chart.chart-sm`, 250px high. [Chart setup](/nextjs/docs/charts/overview/#chartjs) has the other heights.

## Cutout and colors

`cutout` is the size of the hole, as a percentage of the radius or in pixels. Raise it for a thinner ring:

```tsx
options: {
  maintainAspectRatio: false,
  cutout: "80%",
},
```

The "Other" slice uses the fixed `#dee2e6` from the HTML example. `theme["gray-300"]` is that gray in light mode and follows the gray scale of dark mode.

## ApexCharts example

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

ApexCharts calls this chart type `"donut"`. Its series is a plain array of numbers, one per slice. The file starts with `"use client"`, like the Chart.js one.

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

<script>
var options = {
  chart: {
    height: 350,
    type: "donut",
  },
  dataLabels: {
    enabled: false
  },
  series: [44, 55, 13, 33]
}
adminkit.apexcharts("#apexcharts-doughnut", function () {
  return options;
});
</script>
```
```tsx code title="src/components/sources-donut-chart.tsx"
"use client";

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

export function SourcesDonutChart() {
  return (
    <div className="position-relative" style={{ minHeight: 365 }}>
      <ApexChart
        options={() => ({
          chart: { height: 350, type: "donut" },
          dataLabels: { enabled: false },
          series: [44, 55, 13, 33],
        })}
      />
    </div>
  );
}
```

The slices take the primary, success, warning and danger colors and the borders the surface color (`theme.white`). On a color mode change, `ApexChart` draws the donut again without animation, with the new colors.

## Accessibility

- The `<canvas>` of `ChartJs` has `role="img"`. Screen readers do not read the slices, so add an `aria-label` and write the shares in text.
- The Chart.js example hides the legend, so only color tells the sources apart. Show the legend or name them next to the chart.
- Under `prefers-reduced-motion`, the charts draw without the entrance animation.

## Related

- [React doughnut chart](/react/docs/charts/doughnut-chart/): the same chart in AdminKit for React (Vite)
- [Bootstrap 5 doughnut chart](/bootstrap/docs/charts/doughnut-chart/): the doughnut chart of the HTML version
- [Chart setup](/nextjs/docs/charts/overview/): the `ChartJs`, `ApexChart` and `VectorMap` components
- [Pie chart](/nextjs/docs/charts/pie-chart/): the same data without the hole
- [Chart.js demo](https://nextjs-demo.adminkit.io/charts-chartjs)

---

Canonical HTML page: https://adminkit.io/nextjs/docs/charts/doughnut-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
