AdminKitDocs
Charts

Next.js Line Chart

Draw a Next.js line chart with Chart.js in a client component: monthly sales and orders that redraw in the new colors when the color mode changes.

Line charts are for trends: how sales, visits or orders move from one month to the next. AdminKit for Next.js draws them with the ChartJs component, in the free and PRO versions. AdminKit PRO adds ApexChart for ApexCharts.

Chart.js needs the browser's canvas, so ChartJs is a client component, marked "use client". Its config is a function of the theme colors. Your page is a server component, and functions cannot cross from a server component to a client component. So the chart goes in a small client component of its own, which your page renders. Chart setup covers both chart components.

Example

Sales and orders over twelve months. The lines are curved because AdminKit sets tension: 0.4 as a Chart.js default.

src/components/sales-line-chart.tsx
"use client";

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

export function SalesLineChart() {
  return (
    <div className="chart">
      <ChartJs
        aria-label="Sales and orders per month"
        config={(theme) => ({
          type: "line",
          data: {
            labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
            datasets: [
              {
                label: "Sales ($)",
                fill: true,
                backgroundColor: "transparent",
                borderColor: theme.primary,
                data: [2115, 1562, 1584, 1892, 1487, 2223, 2966, 2448, 2905, 3838, 2917, 3327],
              },
              {
                label: "Orders",
                fill: true,
                backgroundColor: "transparent",
                borderColor: "#adb5bd",
                borderDash: [4, 4],
                data: [958, 724, 629, 883, 915, 1214, 1476, 1212, 1554, 2128, 1466, 1827],
              },
            ],
          },
          options: {
            maintainAspectRatio: false,
            plugins: {
              legend: { display: false },
              tooltip: { intersect: false },
              filler: { propagate: false },
            },
            scales: {
              x: {
                grid: { color: "rgba(0,0,0,0.05)" },
                border: { color: "rgba(0,0,0,0.05)" },
              },
              y: {
                ticks: { stepSize: 500 },
                grid: { color: "transparent" },
              },
            },
          },
        })}
      />
    </div>
  );
}

Render it from the page, which stays a server component:

src/app/(dashboard)/reports/page.tsx
import { SalesLineChart } from "@/components/sales-line-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 and orders</h2>
        </div>
        <div className="card-body">
          <SalesLineChart />
        </div>
      </div>
    </>
  );
}

The static HTML holds a skeleton in the .chart box, and the chart draws in the browser after hydration.

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 container needs a height, and .chart gives it 300px. The other heights are on Chart setup.

Straight lines and filled areas

Two dataset options change the shape. tension: 0 gives straight segments. A backgroundColor other than "transparent", with fill: true, turns the line into an area chart. Chart.js' color helper, which AdminKit's wrapper also uses, makes a theme color transparent:

import { color } from "chart.js/helpers";

// in the datasets of config(theme)
{
  label: "Sales ($)",
  fill: true,
  tension: 0,
  backgroundColor: color(theme.primary).alpha(0.2).rgbString(),
  borderColor: theme.primary,
  data: [2115, 1562, 1584, 1892, 1487, 2223],
}

Colors in dark mode

The "Orders" line (#adb5bd) and the x grid (rgba(0,0,0,0.05)) keep the fixed colors of the HTML example, in both modes. Read theme["gray-500"] instead: it is #adb5bd in light mode and follows the gray scale of dark mode. Leave grid.color out and the grid takes the border color that AdminKit sets for the current mode.

ApexCharts example

Pro

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

In this version, ApexChart draws three series, each with its own line width (stroke.width) and dash (stroke.dashArray). Like ChartJs, it goes in a "use client" file, and it loads ApexCharts only in the browser.

src/components/visits-line-chart.tsx
"use client";

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

export function VisitsLineChart() {
  return (
    <div className="position-relative" style={{ minHeight: 365 }}>
      <ApexChart
        options={() => ({
          chart: { height: 350, type: "line", zoom: { enabled: false } },
          dataLabels: { enabled: false },
          stroke: { width: [5, 7, 5], curve: "straight", dashArray: [0, 8, 5] },
          series: [
            { name: "Session Duration", data: [45, 52, 38, 24, 33, 26, 21, 20, 6, 8, 15, 10] },
            { name: "Page Views", data: [35, 41, 62, 42, 13, 18, 29, 37, 36, 51, 32, 35] },
            { name: "Total Visits", data: [87, 57, 74, 99, 75, 38, 62, 47, 82, 56, 45, 47] },
          ],
          markers: { size: 0 },
          xaxis: {
            categories: ["01 Jan", "02 Jan", "03 Jan", "04 Jan", "05 Jan", "06 Jan", "07 Jan", "08 Jan", "09 Jan", "10 Jan", "11 Jan", "12 Jan"],
          },
          tooltip: {
            y: [
              { title: { formatter: (val: string) => val + " (mins)" } },
              { title: { formatter: (val: string) => val + " per session" } },
              { title: { formatter: (val: string) => val } },
            ],
          },
          grid: { borderColor: "#f1f1f1" },
        })}
      />
    </div>
  );
}

Accessibility

  • ChartJs gives its <canvas> role="img". Screen readers cannot read the lines, so add an aria-label and state the key figures in text.
  • "Orders" is dashed, so it differs from "Sales ($)" by more than color. The legend is hidden, so name both series near the chart.
  • Under prefers-reduced-motion, the charts draw without the entrance animation.

Last updated on

On this page