Overview
TheChart 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
Copy
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.Copy
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.
Copy
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.
Copy
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.
Copy
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.
Copy
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.
Copy
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.Copy
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' }}
/>
);
}