Nexus DSdocs

Chart

Installation

npm install clsx@^2.1.1 recharts@^3.8.1 tailwind-merge@^3.4.0
lib/utils.ts
components/chart/chart.tsx
components/chart/index.ts

Code

'use client';

import { useId } from 'react';

import { Bar, BarChart, CartesianGrid, XAxis } from 'recharts';

import {
  type ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from '@/components/chart/chart';

const data = [
  { month: 'January', desktop: 186, mobile: 80 },
  { month: 'February', desktop: 305, mobile: 200 },
  { month: 'March', desktop: 237, mobile: 120 },
  { month: 'April', desktop: 173, mobile: 190 },
  { month: 'May', desktop: 209, mobile: 130 },
  { month: 'June', desktop: 264, mobile: 140 },
];

const config = {
  desktop: {
    label: 'Desktop',
    color: 'var(--nx-color-chart-categorical-1)',
    icon: DesktopSwatch,
  },
  mobile: {
    label: 'Mobile',
    color: 'var(--nx-color-chart-categorical-2)',
    icon: MobileSwatch,
  },
} satisfies ChartConfig;

const shortMonth = (value: string) => value.slice(0, 3);

function HatchPattern({ id }: { id: string }) {
  return (
    <pattern id={id} width={6} height={6} patternUnits="userSpaceOnUse">
      <rect width={6} height={6} fill="var(--color-mobile)" />
      <path
        d="M0 0L6 6M-3 3L3 9M3 -3L9 3"
        stroke="var(--nx-color-container)"
        strokeWidth={1.5}
      />
    </pattern>
  );
}

function DesktopSwatch() {
  return (
    <svg viewBox="0 0 12 12" aria-hidden="true">
      <rect width={12} height={12} rx={2} fill="var(--color-desktop)" />
    </svg>
  );
}

function MobileSwatch() {
  const pattern = useId();

  return (
    <svg viewBox="0 0 12 12" aria-hidden="true">
      <defs>
        <HatchPattern id={pattern} />
      </defs>
      <rect width={12} height={12} rx={2} fill={`url(#${pattern})`} />
    </svg>
  );
}

export default function ChartDemo() {
  const mobilePattern = useId();

  return (
    <ChartContainer config={config} className="nx:w-full nx:max-w-md">
      <BarChart data={data}>
        <defs>
          <HatchPattern id={mobilePattern} />
        </defs>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          tickFormatter={shortMonth}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Bar dataKey="desktop" fill="var(--color-desktop)" radius={4} />
        <Bar dataKey="mobile" fill={`url(#${mobilePattern})`} radius={4} />
      </BarChart>
    </ChartContainer>
  );
}

Props

ChartContainer

ChartContainer props
PropTypeDefaultDescription
configRequiredChartConfigNo default documentedNo description

ChartLegend

ChartLegend adds no props of its own; it accepts the props of the element or primitive it wraps.

ChartLegendContent

ChartLegendContent props
PropTypeDefaultDescription
classNamestringNo default documentedNo description
hideIconbooleanfalseNo description
nameKeystringNo default documentedNo description
verticalAlign"bottom" | "top""bottom"No description

ChartTooltip

ChartTooltip adds no props of its own; it accepts the props of the element or primitive it wraps.

ChartTooltipContent

ChartTooltipContent props
PropTypeDefaultDescription
activebooleanNo default documentedNo description
classNamestringNo default documentedNo description
colorstringNo default documentedNo description
formatterChartTooltipFormatterNo default documentedNo description
hideIndicatorbooleanfalseNo description
hideLabelbooleanfalseNo description
indicator"dashed" | "line" | "dot""dot"No description
labelKeystringNo default documentedNo description
nameKeystringNo default documentedNo description

Examples

Area

'use client';

import { Area, AreaChart, CartesianGrid, XAxis } from 'recharts';

import {
  type ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from '@/components/chart/chart';

const data = [
  { month: 'January', desktop: 186, mobile: 80 },
  { month: 'February', desktop: 305, mobile: 200 },
  { month: 'March', desktop: 237, mobile: 120 },
  { month: 'April', desktop: 173, mobile: 190 },
  { month: 'May', desktop: 209, mobile: 130 },
  { month: 'June', desktop: 264, mobile: 140 },
];

const config = {
  desktop: {
    label: 'Desktop',
    color: 'var(--nx-color-chart-categorical-1)',
    icon: DesktopSwatch,
  },
  mobile: {
    label: 'Mobile',
    color: 'var(--nx-color-chart-categorical-2)',
    icon: MobileSwatch,
  },
} satisfies ChartConfig;

const shortMonth = (value: string) => value.slice(0, 3);

function AreaSwatch({ color, dashed }: { color: string; dashed?: boolean }) {
  return (
    <svg viewBox="0 0 12 12" aria-hidden="true">
      <rect
        x={1}
        y={1}
        width={10}
        height={10}
        rx={2}
        fill={color}
        fillOpacity={0.4}
        stroke={color}
        strokeWidth={1.5}
        strokeDasharray={dashed ? '3 2' : undefined}
      />
    </svg>
  );
}

function DesktopSwatch() {
  return <AreaSwatch color="var(--color-desktop)" />;
}

function MobileSwatch() {
  return <AreaSwatch color="var(--color-mobile)" dashed />;
}

export default function ChartArea() {
  return (
    <ChartContainer config={config} className="nx:w-full nx:max-w-md">
      <AreaChart data={data} margin={{ left: 12, right: 12 }}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          tickFormatter={shortMonth}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Area
          dataKey="desktop"
          type="natural"
          fill="var(--color-desktop)"
          fillOpacity={0.4}
          stroke="var(--color-desktop)"
        />
        <Area
          dataKey="mobile"
          type="natural"
          fill="var(--color-mobile)"
          fillOpacity={0.4}
          stroke="var(--color-mobile)"
          strokeDasharray="6 4"
        />
      </AreaChart>
    </ChartContainer>
  );
}

Line

'use client';

import { CartesianGrid, Line, LineChart, XAxis } from 'recharts';

import {
  type ChartConfig,
  ChartContainer,
  ChartLegend,
  ChartLegendContent,
  ChartTooltip,
  ChartTooltipContent,
} from '@/components/chart/chart';

const data = [
  { month: 'January', desktop: 186, mobile: 80 },
  { month: 'February', desktop: 305, mobile: 200 },
  { month: 'March', desktop: 237, mobile: 120 },
  { month: 'April', desktop: 173, mobile: 190 },
  { month: 'May', desktop: 209, mobile: 130 },
  { month: 'June', desktop: 264, mobile: 140 },
];

const config = {
  desktop: {
    label: 'Desktop',
    color: 'var(--nx-color-chart-categorical-1)',
    icon: DesktopSwatch,
  },
  mobile: {
    label: 'Mobile',
    color: 'var(--nx-color-chart-categorical-2)',
    icon: MobileSwatch,
  },
} satisfies ChartConfig;

const shortMonth = (value: string) => value.slice(0, 3);

function LineSwatch({ color, dashed }: { color: string; dashed?: boolean }) {
  return (
    <svg viewBox="0 0 12 12" aria-hidden="true">
      <line
        x1={0}
        y1={6}
        x2={12}
        y2={6}
        stroke={color}
        strokeWidth={2}
        strokeDasharray={dashed ? '3 2' : undefined}
      />
    </svg>
  );
}

function DesktopSwatch() {
  return <LineSwatch color="var(--color-desktop)" />;
}

function MobileSwatch() {
  return <LineSwatch color="var(--color-mobile)" dashed />;
}

export default function ChartLine() {
  return (
    <ChartContainer config={config} className="nx:w-full nx:max-w-md">
      <LineChart data={data} margin={{ left: 12, right: 12 }}>
        <CartesianGrid vertical={false} />
        <XAxis
          dataKey="month"
          tickLine={false}
          axisLine={false}
          tickMargin={8}
          tickFormatter={shortMonth}
        />
        <ChartTooltip content={<ChartTooltipContent />} />
        <ChartLegend content={<ChartLegendContent />} />
        <Line
          dataKey="desktop"
          type="natural"
          stroke="var(--color-desktop)"
          strokeWidth={2}
          dot={false}
        />
        <Line
          dataKey="mobile"
          type="natural"
          stroke="var(--color-mobile)"
          strokeDasharray="6 4"
          strokeWidth={2}
          dot={false}
        />
      </LineChart>
    </ChartContainer>
  );
}