AdminKitDocs
Charts

Next.js Pie Chart

A Next.js pie chart in a "use client" component: Chart.js slices for traffic sources, rendered from an App Router page and colored by the theme.

Use a pie chart to show shares of a total, such as visits per traffic source. In AdminKit for Next.js, the ChartJs component draws it with Chart.js, in the free and PRO versions. AdminKit PRO can draw the same chart with ApexCharts through ApexChart.

Chart.js runs in the browser, so ChartJs is a client component. Its config prop is a function of the theme colors. Your page is a server component, and a server component cannot pass a function to a client component. So put the chart in a file that starts with "use client", and render it from the page. Chart setup has the details.

Example

Visits per traffic source, one theme color per slice.

src/components/traffic-pie-chart.tsx
"use client";

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

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

The page imports it and keeps its metadata export:

src/app/(dashboard)/traffic/page.tsx
import { TrafficPieChart } from "@/components/traffic-pie-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">
          <TrafficPieChart />
        </div>
      </div>
    </>
  );
}

The exported HTML has a skeleton in the chart's place. The slices draw after hydration, once the theme colors are known.

Props

PropTypeDefaultDescription
config(theme: Theme) => ChartConfigurationThe 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 draws its pie chart in .chart.chart-sm, 250px high. Chart setup lists the other heights.

Legend and slice colors

The legend is hidden in the example. legend.display: true shows it, and legend.position places it:

plugins: { legend: { display: true, position: "bottom" } },

"Other" uses the fixed #dee2e6 of the HTML example. theme["gray-300"] gives the same gray in light mode and a gray of the dark scale in dark mode.

ApexCharts example

Pro

This example is only available in AdminKit PRO. Learn more.

ApexCharts takes the series of a pie chart as a plain array of numbers, one per slice. Without labels, the legend calls them "series-1" to "series-4", so set labels to name them. ApexChart is a client component too, so this file starts with "use client" as well.

src/components/sources-pie-chart.tsx
"use client";

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

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

On pie, donut and polar area charts, ApexChart draws the slice borders in the surface color (theme.white) unless the options set stroke.colors. When the color mode changes, it draws these charts again without animation, so the borders, labels and legend take the new colors.

Accessibility

  • ChartJs renders a <canvas> with role="img". Screen readers do not read the slices. Give it an aria-label, and show the shares that matter in text, such as a list next to the chart.
  • With the legend hidden, only color tells the slices apart. Show the legend or name the sources in text.
  • Under prefers-reduced-motion, the charts draw without the entrance animation.

Last updated on

On this page