Skip to main content

Overview

The Chart component wraps Recharts primitives with the DevReady visual language. It ships with line, barStandard, barPairs, barSplit, pie, pieFull, and pieRing variants plus reusable tooltip/legend helpers and utilities such as selectEvenlySpacedItems.

Basic Usage

import {
  Chart,
  ChartLegendContent,
  ChartTooltipContent,
} from '@peppermint-design/devreadykit-custom';

const data = [
{ date: new Date(2025, 0, 1), desktop: 420, mobile: 260 },
{ date: new Date(2025, 0, 2), desktop: 430, mobile: 275 },
];

const series = [
{ dataKey: 'desktop', name: 'Desktop' },
{ dataKey: 'mobile', name: 'Mobile' },
];

export default function LineChartExample() {
  return (
    <Chart
      variant="line"
      data={data}
      xKey="date"
      series={series}
    />
  );
}

Formatting

Pass formatter callbacks to customise the tooltip and axes.
import {
  Chart,
  ChartLegendContent,
  ChartTooltipContent,
} from '@peppermint-design/devreadykit-custom';
import { useBreakpoint } from '@/hooks/use-breakpoint';

const data = [
{ date: new Date(2025, 0, 1), desktop: 420, mobile: 260 },
{ date: new Date(2025, 0, 2), desktop: 430, mobile: 275 },
{ date: new Date(2025, 0, 3), desktop: 446, mobile: 290 },
];

const series = [
{
dataKey: 'desktop',
name: 'Desktop',
colorClassName: 'text-primary-50',
},
{
dataKey: 'mobile',
name: 'Mobile',
colorClassName: 'text-primary-30',
},
];

export default function FormattedLineChart() {
  const isDesktop = useBreakpoint('lg');

return (
<Chart
variant="line"
data={data}
xKey="date"
series={series}
height={280}
margin={{ top: 24, right: isDesktop ? 36 : 16, bottom: 16, left: 16 }}
grid={{ show: true, horizontal: true, vertical: false }}
legendContent={(props) => (
<ChartLegendContent
{...props}
className={isDesktop ? 'flex-col items-end gap-200' : 'justify-center'}
/>
)}
legendProps={{
        layout: isDesktop ? 'vertical' : 'horizontal',
        align: isDesktop ? 'right' : 'center',
        verticalAlign: isDesktop ? 'middle' : 'top',
      }}
tooltipFormatter={(value) =>
typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
}
tooltipLabelFormatter={(value) =>
value instanceof Date
? value.toLocaleDateString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
})
: String(value ?? '')
}
tooltipProps={{
        content: <ChartTooltipContent className="min-w-[220px]" />,
      }}
xAxisTickFormatter={(value) =>
value instanceof Date
? value.toLocaleDateString(undefined, { weekday: 'short' })
: String(value)
}
/>
);
}

Bar Variants

Stacked (barStandard)

Combine bars with optional line overlays. The selectEvenlySpacedItems helper keeps X axis ticks legible for large datasets, and the showYAxis flag lets you match different layouts.
import {
  Chart,
  ChartTooltipContent,
  selectEvenlySpacedItems,
} from '@peppermint-design/devreadykit-custom';

const data = [
  { date: new Date(2025, 0, 1), actual: 420, goal: 460 },
  { date: new Date(2025, 0, 8), actual: 520, goal: 480 },
  { date: new Date(2025, 0, 15), actual: 610, goal: 500 },
  // ...
];

const bars = [{ dataKey: 'actual', name: 'Completed' }];

const lineSeries = [
  { dataKey: 'goal', name: 'Goal', colorClassName: 'text-primary-30', strokeDasharray: '4 6', dot: false, activeDot: false },
];

const ticks = selectEvenlySpacedItems(data, 6).map((item) => item.date);

export default function BarChartExample() {
  return (
    <Chart
      variant="barStandard"
      data={data}
      xKey="date"
      bars={bars}
      lineSeries={lineSeries}
      showYAxis={false}
      xAxisProps={{ ticks }}
      xAxisTickFormatter={(value) =>
        value instanceof Date
          ? value.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })
          : String(value)
      }
      tooltipFormatter={(value) =>
        typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
      }
      tooltipProps={{ content: <ChartTooltipContent className="min-w-[220px]" /> }}
    />
  );
}

Paired (barPairs)

Render side-by-side bars for quick comparisons between two categories.
import {
  Chart,
  ChartTooltipContent,
  selectEvenlySpacedItems,
} from '@peppermint-design/devreadykit-custom';

const data = [
{ date: new Date(2025, 0, 6), desktop: 540, mobile: 320 },
{ date: new Date(2025, 0, 7), desktop: 660, mobile: 400 },
// ...
];

const bars = [
{ dataKey: 'desktop', name: 'Desktop', colorClassName: 'text-primary-50', maxBarSize: 18 },
{ dataKey: 'mobile', name: 'Mobile', colorClassName: 'text-success-40', maxBarSize: 18 },
];

const ticks = selectEvenlySpacedItems(data, 6).map((item) => item.date);

export default function PairedBarExample() {
  return (
    <Chart
      variant="barPairs"
      data={data}
      xKey="date"
      bars={bars}
      showYAxis={false}
      barCategoryGap={32}
      xAxisProps={{ ticks }}
      xAxisTickFormatter={(value) =>
        value instanceof Date
          ? value.toLocaleDateString(undefined, { weekday: 'short' })
          : String(value)
      }
      tooltipFormatter={(value) =>
        typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
      }
      tooltipProps={{ content: <ChartTooltipContent className="min-w-[220px]" /> }}
    />
  );
}

Split (barSplit)

Visualise positive and negative contributions sharing a zero baseline.
import {
  Chart,
  ChartTooltipContent,
  selectEvenlySpacedItems,
} from '@peppermint-design/devreadykit-custom';

const data = [
{ date: new Date(2025, 0, 6), gains: 100, losses: -140 },
{ date: new Date(2025, 0, 7), gains: 120, losses: -180 },
// ...
];

const bars = [
{ dataKey: 'gains', name: 'Gains', colorClassName: 'text-warning-50', stackId: 'split', splitDirection: 'positive', splitCornerRadius: 4 },
{ dataKey: 'losses', name: 'Losses', colorClassName: 'text-error-50', stackId: 'split', splitDirection: 'negative', splitCornerRadius: 4 },
];

const ticks = selectEvenlySpacedItems(data, 6).map((item) => item.date);

export default function SplitBarExample() {
  return (
    <Chart
      variant="barSplit"
      data={data}
      xKey="date"
      bars={bars}
      showYAxis={false}
      barCategoryGap={40}
      xAxisProps={{ ticks }}
      xAxisTickFormatter={(value) =>
        value instanceof Date
          ? value.toLocaleDateString(undefined, { weekday: 'short' })
          : String(value)
      }
      tooltipFormatter={(value) =>
        typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
      }
      tooltipProps={{ content: <ChartTooltipContent className="min-w-[220px]" /> }}
    />
  );
}

Full Pie (pieFull)

Fill the entire circle while keeping the same API as the doughnut variant.
import { Chart } from '@peppermint-design/devreadykit-custom';

const data = [
{ name: 'North', value: 320, className: 'text-success-50' },
{ name: 'West', value: 180, className: 'text-primary-40' },
{ name: 'South', value: 140, className: 'text-error-50' },
{ name: 'East', value: 90, className: 'text-warning-50' },
];

export default function FullPieExample() {
  return (
    <Chart
      variant="pieFull"
      data={data}
      dataKey="value"
      nameKey="name"
      tooltipFormatter={(value) =>
        typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
      }
      legendProps={{ layout: 'horizontal', verticalAlign: 'bottom', align: 'center' }}
    />
  );
}

Ring (pieRing)

Display multiple progress rings with a shared center label.
import { Chart } from '@peppermint-design/devreadykit-custom';

const rings = [
{ name: 'North', value: 750, total: 1000, className: 'text-error-50' },
{ name: 'West', value: 620, total: 1000, className: 'text-success-50' },
{ name: 'South', value: 540, total: 1000, className: 'text-primary-40' },
];

export default function PieRingExample() {
  return (
    <Chart
      variant="pieRing"
      data={rings}
      valueKey="value"
      totalKey="total"
      nameKey="name"
      thickness={14}
      gap={6}
      centerLabel="Label"
      centerValue="1,000"
      legendProps={{ layout: 'horizontal', verticalAlign: 'bottom', align: 'center' }}
    />
  );
}

Pie Variant

Render doughnut and pie charts with themed legends and tooltips.
import { Chart } from '@peppermint-design/devreadykit-custom';

const data = [
{ name: 'North', value: 320, className: 'text-success-50' },
{ name: 'West', value: 180, className: 'text-primary-40' },
{ name: 'South', value: 140, className: 'text-error-50' },
{ name: 'East', value: 90, className: 'text-warning-50' },
];

export default function PieExample() {
  return (
    <Chart
      variant="pie"
      data={data}
      dataKey="value"
      nameKey="name"
      innerRadius="55%"
      outerRadius="80%"
      tooltipFormatter={(value) =>
        typeof value === 'number' ? value.toLocaleString() : String(value ?? '')
      }
      legendProps={{ layout: 'vertical', align: 'right', verticalAlign: 'middle' }}
    />
  );
}

Props

Line variant

Bar variant ("barStandard" & "barPairs")

Pie variant ("pie" & "pieFull")

Ring variant ("pieRing")