> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devreadykit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Charts

> Responsive data visualisation components built on top of Recharts.

## Overview

The `Chart` component wraps [Recharts](https://recharts.org/) 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

<CodeGroup>
  ```tsx theme={null}
  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}
      />
    );
  }
  ```
</CodeGroup>

## Formatting

Pass formatter callbacks to customise the tooltip and axes.

<CodeGroup>
  ```tsx theme={null}
  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)
  }
  />
  );
  }

  ```
</CodeGroup>

## 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.

<CodeGroup>
  ```tsx theme={null}
  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]" /> }}
      />
    );
  }
  ```
</CodeGroup>

### Paired (`barPairs`)

Render side-by-side bars for quick comparisons between two categories.

<CodeGroup>
  ```tsx theme={null}
  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]" /> }}
      />
    );
  }
  ```
</CodeGroup>

### Split (`barSplit`)

Visualise positive and negative contributions sharing a zero baseline.

<CodeGroup>
  ```tsx theme={null}
  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]" /> }}
      />
    );
  }
  ```
</CodeGroup>

### Full Pie (`pieFull`)

Fill the entire circle while keeping the same API as the doughnut variant.

<CodeGroup>
  ```tsx theme={null}
  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' }}
      />
    );
  }
  ```
</CodeGroup>

### Ring (`pieRing`)

Display multiple progress rings with a shared center label.

<CodeGroup>
  ```tsx theme={null}
  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' }}
      />
    );
  }
  ```
</CodeGroup>

## Pie Variant

Render doughnut and pie charts with themed legends and tooltips.

<CodeGroup>
  ```tsx theme={null}
  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' }}
      />
    );
  }
  ```
</CodeGroup>

## Props

<PropsTable>
  | Prop                  | Type                                                                        | Default                                        | Description                                                    |
  | :-------------------- | :-------------------------------------------------------------------------- | :--------------------------------------------- | :------------------------------------------------------------- |
  | variant               | `"line" \| "barStandard" \| "barPairs" \| "barSplit" \| "pie" \| "pieFull"` | `"line"`                                       | Selects the visual chart variant                               |
  | data                  | `Array<Record<string, number \| string \| Date>>`                           | `[]`                                           | Dataset passed to Recharts                                     |
  | xKey                  | `string`                                                                    | -                                              | Key used for the X axis (`line`/`bar` variants)                |
  | height                | `number`                                                                    | `240`                                          | Height in pixels                                               |
  | margin                | `ChartMargin`                                                               | `{ top: 12, right: 16, bottom: 12, left: 16 }` | Inner chart margin                                             |
  | grid                  | `boolean \| ChartGridOptions`                                               | `true`                                         | Grid visibility and styling                                    |
  | showLegend            | `boolean`                                                                   | `true`                                         | Toggles the legend                                             |
  | legendContent         | `LegendProps["content"]`                                                    | `<ChartLegendContent />`                       | Custom legend renderer                                         |
  | legendProps           | `LegendProps`                                                               | `{}`                                           | Additional legend props                                        |
  | showTooltip           | `boolean`                                                                   | `true`                                         | Toggles the tooltip                                            |
  | tooltipFormatter      | `Formatter`                                                                 | Locale number formatter                        | Formats tooltip values                                         |
  | tooltipLabelFormatter | `(label) => ReactNode`                                                      | Locale date formatter                          | Formats tooltip labels                                         |
  | tooltipProps          | `TooltipProps<number \| string, string>`                                    | `{}`                                           | Extra props forwarded to `recharts`' `<Tooltip>`               |
  | xAxisTickFormatter    | `(value) => string`                                                         | Locale month                                   | Formats X axis ticks                                           |
  | yAxisTickFormatter    | `(value) => string`                                                         | Locale number                                  | Formats Y axis ticks                                           |
  | showXAxis             | `boolean`                                                                   | `true`                                         | Renders or hides the XAxis                                     |
  | showYAxis             | `boolean`                                                                   | `true`                                         | Renders or hides the YAxis                                     |
  | xAxisChildren         | `ReactNode`                                                                 | -                                              | Optional children rendered inside `<XAxis>` (e.g. `<Label />`) |
  | yAxisChildren         | `ReactNode`                                                                 | -                                              | Optional children rendered inside `<YAxis>`                    |
</PropsTable>

### Line variant

<PropsTable>
  | Prop   | Type                | Default | Description               |
  | :----- | :------------------ | :------ | :------------------------ |
  | series | `LineChartSeries[]` | `[]`    | Line series configuration |
</PropsTable>

### Bar variant (`"barStandard"` & `"barPairs"`)

<PropsTable>
  | Prop              | Type                                        | Default         | Description                                                                                               |
  | :---------------- | :------------------------------------------ | :-------------- | :-------------------------------------------------------------------------------------------------------- |
  | bars              | `BarChartBarSeries[]`                       | `[]`            | Bar series configuration                                                                                  |
  | lineSeries        | `LineChartSeries[]`                         | `[]`            | Optional line overlays rendered above the bars                                                            |
  | barCategoryGap    | `number \| string`                          | Theme default   | Category gap passed to `ComposedChart`                                                                    |
  | barGap            | `number \| string`                          | Theme default   | Bar gap passed to `ComposedChart`                                                                         |
  | variant           | `"barStandard" \| "barPairs" \| "barSplit"` | `"barStandard"` | Selects stacked (standard), paired, or split grouping                                                     |
  | splitDirection    | `"positive" \| "negative"`                  | `"positive"`    | For `barSplit`, controls whether the series renders above (`positive`) or below (`negative`) the baseline |
  | splitCornerRadius | `number`                                    | `4`             | Corner radius applied to split bars (after rotation for negatives)                                        |
  | splitGap          | `number`                                    | `6`             | Gap between split bars and the zero baseline                                                              |
</PropsTable>

### Pie variant (`"pie"` & `"pieFull"`)

<PropsTable>
  | Prop              | Type                       | Default                              | Description                                       |
  | :---------------- | :------------------------- | :----------------------------------- | :------------------------------------------------ |
  | dataKey           | `string`                   | -                                    | Key holding the slice value                       |
  | nameKey           | `string`                   | `'name'`                             | Key holding the slice label                       |
  | innerRadius       | `number \| string`         | `'55%'` (`pie`), `0` (`pieFull`)     | Inner radius                                      |
  | outerRadius       | `number \| string`         | `'80%'` (`pie`), `'90%'` (`pieFull`) | Outer radius of the pie                           |
  | startAngle        | `number`                   | `-270`                               | Starting angle in degrees                         |
  | endAngle          | `number`                   | `-630`                               | Ending angle in degrees                           |
  | paddingAngle      | `number`                   | `0`                                  | Gap between slices                                |
  | cornerRadius      | `number`                   | `0`                                  | Rounds slice edges                                |
  | classNameKey      | `string`                   | `'className'`                        | Key that maps to the slice color class            |
  | getSliceClassName | `(slice, index) => string` | -                                    | Custom resolver for slice classes                 |
  | pieProps          | `Partial<PieProps>`        | `{ isAnimationActive: false }`       | Additional props forwarded to `recharts`' `<Pie>` |
</PropsTable>

### Ring variant (`"pieRing"`)

<PropsTable>
  | Prop                 | Type                | Default                        | Description                                 |
  | :------------------- | :------------------ | :----------------------------- | :------------------------------------------ |
  | valueKey             | `string`            | `'value'`                      | Key holding the progress value              |
  | totalKey             | `string`            | -                              | Key holding the total (defaults to `value`) |
  | nameKey              | `string`            | `'name'`                       | Key rendered in the legend                  |
  | classNameKey         | `string`            | `'className'`                  | Key mapping to the ring color class         |
  | trackClassNameKey    | `string`            | -                              | Key mapping to the ring background class    |
  | thickness            | `number`            | `12`                           | Thickness of each ring in pixels            |
  | gap                  | `number`            | `6`                            | Gap between rings in pixels                 |
  | outerRadius          | `number`            | `88`                           | Outer radius of the outermost ring          |
  | cornerRadius         | `number`            | `thickness / 2`                | Roundness applied to ring ends              |
  | startAngle           | `number`            | `-270`                         | Starting angle for all rings                |
  | centerLabel          | `ReactNode`         | -                              | Optional text shown inside the rings        |
  | centerValue          | `ReactNode`         | -                              | Optional value shown inside the rings       |
  | centerLabelClassName | `string`            | -                              | Additional classes for the center label     |
  | centerValueClassName | `string`            | -                              | Additional classes for the center value     |
  | ringPieProps         | `Partial<PieProps>` | `{ isAnimationActive: false }` | Props forwarded to the value pies           |
  | trackPieProps        | `Partial<PieProps>` | `{ isAnimationActive: false }` | Props forwarded to the track pies           |
</PropsTable>
