> For AI agents: the complete documentation index is available at https://wallarm.github.io/design-system/llms.txt, the full documentation bundle is available at https://wallarm.github.io/design-system/llms-full.txt.

# SimpleCharts

[Source](https://github.com/wallarm/design-system/tree/main/packages/design-system/src/components/SimpleCharts) · [Storybook](https://wallarm.github.io/design-system/storybook/?path=/docs/data-display-simplecharts-areachart--overview)

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartXAxis, LineChartYAxis, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from '../LineChart/lib/sampleData';

export const Default = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-560'>
      <Chart data-testid='chart'>
        <ChartHeader>
          <ChartTitle>Traffic breakdown (stacked)</ChartTitle>
        </ChartHeader>
        <AreaChart
          data-testid='area-chart'
          data={hourlyData24}
          series={multiSeries}
          xKey='timestamp'
        >
          <MultiLegend />
          <AreaChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <AreaChartArea key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </AreaChartBody>
        </AreaChart>
      </Chart>
    </div>
  );
};
```

## Usage

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartXAxis, LineChartYAxis, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';
```

## Examples

### AreaChart

#### Standard

Standard (overlaid) variant — each series draws from the baseline independently with
transparency, useful when stacking would be misleading.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartXAxis, LineChartYAxis, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from '../LineChart/lib/sampleData';

export const Standard = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-560'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Traffic breakdown (standard)</ChartTitle>
        </ChartHeader>
        <AreaChart data={hourlyData24} series={multiSeries} xKey='timestamp' variant='standard'>
          <MultiLegend />
          <AreaChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <AreaChartArea key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </AreaChartBody>
        </AreaChart>
      </Chart>
    </div>
  );
};
```

#### With metric

The metric variant: `Metric` bricks sit to the left of the legend in a row between the
header and the plot.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartXAxis, LineChartYAxis, MetricDelta, MetricHeader, MetricValue, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from '../LineChart/lib/sampleData';

export const WithMetric = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-800'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Requests per hour</ChartTitle>
        </ChartHeader>
        <AreaChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <div className='flex items-center justify-between pr-8'>
            <MetricHeader className='px-16'>
              <MetricValue>{2903}</MetricValue>
              <MetricDelta value={10} trend='up' sentiment='negative' />
            </MetricHeader>
            <MultiLegend />
          </div>
          <AreaChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <AreaChartArea key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </AreaChartBody>
        </AreaChart>
      </Chart>
    </div>
  );
};
```

#### Filterable

Clicking a legend row isolates that series and clicking another adds it back.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartTooltip, LineChartXAxis, LineChartYAxis, AreaChart, AreaChartArea, AreaChartBody } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';
import { hourlyData24, multiSeries } from '../LineChart/lib/sampleData';

export const Filterable = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  const [hidden, setHidden] = useState<string[]>([]);
  const toggle = (key: string) => {
    setHidden(prev => {
      if (prev.length === 0) return multiSeries.filter(s => s.key !== key).map(s => s.key);
      if (prev.includes(key)) return prev.filter(k => k !== key);
      return [...prev, key];
    });
  };
  const filtered = hidden.length > 0;

  return (
    <div className='w-560'>
      <Chart data-testid='chart'>
        <ChartHeader>
          <ChartTitle>Click a row to isolate, click another to add</ChartTitle>
          <ChartActions alwaysVisible={filtered}>
            {filtered && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant='ghost'
                    color='neutral'
                    size='small'
                    aria-label='Clear filter'
                    onClick={() => setHidden([])}
                  >
                    <FilterX />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Remove filter</TooltipContent>
              </Tooltip>
            )}
          </ChartActions>
        </ChartHeader>
        <AreaChart
          data-testid='area-chart'
          data={hourlyData24}
          series={multiSeries}
          xKey='timestamp'
          filteredKeys={hidden}
        >
          <LineChartLegend>
            {multiSeries.map(s => (
              <Tooltip key={s.key}>
                <TooltipTrigger asChild>
                  <LineChartLegendItem seriesKey={s.key} onClick={() => toggle(s.key)}>
                    <LineChartHoverPopoverDot color={s.color} />
                    <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                  </LineChartLegendItem>
                </TooltipTrigger>
                <TooltipContent>
                  {hidden.includes(s.key) ? 'Remove filter' : 'Click to filter'}
                </TooltipContent>
              </Tooltip>
            ))}
          </LineChartLegend>
          <AreaChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <AreaChartArea key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </AreaChartBody>
        </AreaChart>
      </Chart>
    </div>
  );
};
```

#### Zoom

Drag across the plot to choose a range, then confirm in the popover.

```tsx
export const Zoom = () => (
  <div className='w-560'>
    <ZoomControlledChart />
  </div>
);
```

#### Loading

Loading skeleton state composed from the same primitives as a populated chart.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty } from '@wallarm-org/design-system/SimpleCharts';

export const Loading = () => (
  <div className='w-560'>
    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Loading</ChartTitle>
      </ChartHeader>
      <LoadingLegend />
      <LineChartEmpty />
    </Chart>
  </div>
);
```

#### Empty

Empty state — `LineChartEmpty` keeps the dashed plot frame and puts the message inside it.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty } from '@wallarm-org/design-system/SimpleCharts';

export const Empty = () => (
  <div className='w-560'>
    <Chart>
      <ChartHeader>
        <ChartTitle>No data</ChartTitle>
      </ChartHeader>
      <LineChartEmpty>No data</LineChartEmpty>
    </Chart>
  </div>
);
```

### BarList

#### Default

The interactive shape: click a row to filter down to it, and the header's clear button
appears while that filter holds. Filtering recomputes `max` from what is left, which is why
a lone row reads 100%.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const Default = () => {
  const [filtered, setFiltered] = useState<string | null>(null);
  const rows = filtered ? baseRows.filter(r => r.name === filtered) : baseRows;

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
          <ChartActions alwaysVisible={filtered !== null}>
            {filtered !== null && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant='ghost'
                    color='neutral'
                    size='small'
                    aria-label='Clear filter'
                    onClick={() => setFiltered(null)}
                  >
                    <FilterX />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Remove filter</TooltipContent>
              </Tooltip>
            )}
            <Tooltip>
              <TooltipTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
                  <Settings />
                </Button>
              </TooltipTrigger>
              <TooltipContent>Change data source</TooltipContent>
            </Tooltip>
          </ChartActions>
        </ChartHeader>
        <BarList data-testid='bar-list' max={chartSum(rows)}>
          {rows.map(row => (
            <Tooltip key={row.name}>
              <TooltipTrigger asChild>
                <BarListItem
                  value={row.value}
                  selected={filtered === row.name}
                  onClick={() => setFiltered(filtered === row.name ? null : row.name)}
                >
                  <BarListBar />
                  <BarListLabel>{row.name}</BarListLabel>
                  <BarListValue>
                    {formatValue(row.value)}
                    <BarListPercent />
                  </BarListValue>
                </BarListItem>
              </TooltipTrigger>
              <TooltipContent>Click to filter</TooltipContent>
            </Tooltip>
          ))}
        </BarList>
      </Chart>
    </div>
  );
};
```

#### Colored

`color` tints the bar with a palette hue at 16% — enough to distinguish the rows while still
letting the row's own hover state show through it.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const Colored = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <BarList data-testid='bar-list' max={chartMax(baseRows)}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar color={row.color} />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Custom colors

For a hue the palette does not carry, pass a `bg-*` utility on the bar instead — the
explicit class wins the merge against the variant's own fill.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const CustomColors = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <BarList max={chartMax(baseRows)}>
        {baseRows.map((row, i) => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar className={customColorClassNames[i]} />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Percentage

Values that are already percentages: `max={100}`, and the value slot prints the number
itself rather than a share derived from it.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const Percentage = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Response status</ChartTitle>
      </ChartHeader>
      <BarList max={100}>
        {percentageRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>{formatPercent(row.value)}</BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Selectable

`selected` marks the active row — the hover tint and `aria-current` — and never touches the
bar, whose width stays `value / max` whatever is selected.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const Selectable = () => {
  const [selected, setSelected] = useState<string | null>(null);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
          <ChartActions alwaysVisible={selected !== null}>
            {selected !== null && (
              <Button
                variant='ghost'
                color='neutral'
                size='small'
                aria-label='Clear selection'
                onClick={() => setSelected(null)}
              >
                <FilterX />
              </Button>
            )}
          </ChartActions>
        </ChartHeader>
        <BarList data-testid='bar-list' max={chartSum(baseRows)}>
          {baseRows.map(row => (
            <Tooltip key={row.name}>
              <TooltipTrigger asChild>
                <BarListItem
                  value={row.value}
                  selected={selected === row.name}
                  onClick={() => setSelected(selected === row.name ? null : row.name)}
                >
                  <BarListBar />
                  <BarListLabel>{row.name}</BarListLabel>
                  <BarListValue>
                    {formatValue(row.value)}
                    <BarListPercent variant='muted' />
                  </BarListValue>
                </BarListItem>
              </TooltipTrigger>
              <TooltipContent>Click to filter</TooltipContent>
            </Tooltip>
          ))}
        </BarList>
      </Chart>
    </div>
  );
};
```

#### Truncated labels

Long labels truncate at the row width. A tooltip on the label needs `pointer-events-auto`,
since the row's slots are transparent to the pointer by default.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const TruncatedLabels = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <BarList max={chartMax(longLabelRows)}>
        {longLabelRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <Tooltip>
              <TooltipTrigger asChild>
                <BarListLabel className='pointer-events-auto'>{row.name}</BarListLabel>
              </TooltipTrigger>
              <TooltipContent>Example of custom description</TooltipContent>
            </Tooltip>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Truncated labels with tooltip

The same labels under `OverflowTooltip`, which shows the full text only when it is actually
cut off — the right choice when most labels fit.

```tsx
import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from '@wallarm-org/design-system/OverflowTooltip';
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const TruncatedLabelsWithTooltip = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <BarList max={chartMax(longLabelRows)}>
        {longLabelRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <OverflowTooltip>
              <OverflowTooltipTrigger>
                <BarListLabel className='pointer-events-auto'>{row.name}</BarListLabel>
              </OverflowTooltipTrigger>
              <OverflowTooltipContent>{row.name}</OverflowTooltipContent>
            </OverflowTooltip>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Data variants

One card, three datasets behind a settings menu: raw counts, percentages and fractions each
need their own `max`, so switching the source switches that too.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuItemIcon, DropdownMenuLabel, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Check, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';
import { cn } from '@wallarm-org/design-system/utils/cn';

export const DataVariants = () => {
  const [key, setKey] = useState<DatasetKey>('values');
  const [menuOpen, setMenuOpen] = useState(false);
  const current = datasets[key];

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>{current.title}</ChartTitle>
          <ChartActions alwaysVisible={menuOpen}>
            <Tooltip disabled={menuOpen}>
              <TooltipTrigger asChild>
                <span className='inline-flex'>
                  <DropdownMenu onOpenChange={setMenuOpen}>
                    <DropdownMenuTrigger asChild>
                      <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
                        <Settings />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent>
                      <DropdownMenuLabel>Data source</DropdownMenuLabel>
                      <DropdownMenuGroup>
                        {(Object.keys(datasets) as DatasetKey[]).map(k => (
                          <DropdownMenuItem key={k} onSelect={() => setKey(k)}>
                            <span className='flex-1'>{datasets[k].title}</span>
                            <DropdownMenuItemIcon>
                              <Check className={cn(key !== k && 'opacity-0')} />
                            </DropdownMenuItemIcon>
                          </DropdownMenuItem>
                        ))}
                      </DropdownMenuGroup>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </span>
              </TooltipTrigger>
              <TooltipContent>Change data source</TooltipContent>
            </Tooltip>
          </ChartActions>
        </ChartHeader>
        <BarList max={current.max}>
          {current.rows.map(row => (
            <BarListItem key={row.name} value={row.value}>
              <BarListBar color={row.color} />
              <BarListLabel>{row.name}</BarListLabel>
              {current.renderValue(row)}
            </BarListItem>
          ))}
        </BarList>
      </Chart>
    </div>
  );
};
```

#### Loading

`BarListSkeleton` stands in for the list while data loads, taking a row count so the card
holds the height it will end up at.

```tsx
import { Chart, ChartHeader, ChartTitle, BarListSkeleton } from '@wallarm-org/design-system/SimpleCharts';

export const Loading = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <BarListSkeleton data-testid='bar-list-skeleton' rows={5} />
    </Chart>
  </div>
);
```

#### Overflow

A value above `max` caps the bar at full width and the label at 100%, rather than
overrunning the row.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const Overflow = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Overflow & zero</ChartTitle>
      </ChartHeader>
      <BarList data-testid='bar-list' max={100}>
        {overflowRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Invalid max

`max={0}` is not a division the component will guess at: every row renders empty at 0%, with
a single warning in development.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const InvalidMax = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Invalid max</ChartTitle>
      </ChartHeader>
      <BarList data-testid='bar-list' max={0}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Percent digits

`digits` adds decimal places, for a set of shares too close together to tell apart as whole
numbers.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const PercentDigits = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Decimal precision</ChartTitle>
      </ChartHeader>
      <BarList data-testid='bar-list' max={chartSum(baseRows)}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent digits={1} variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

#### Percent variants

The three percent treatments — `split` colours the number and the `%` differently and is the
Figma default, `muted` sets both back, `inherit` leaves them to the row.

```tsx
import { Chart, ChartHeader, ChartTitle, BarList, BarListBar, BarListItem, BarListLabel, BarListPercent, BarListValue } from '@wallarm-org/design-system/SimpleCharts';

export const PercentVariants = () => (
  <div className='flex flex-col gap-16 w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Split — value primary, % secondary (default)</ChartTitle>
      </ChartHeader>
      <BarList data-testid='bar-list-split' max={chartSum(baseRows)}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='split' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>

    <Chart>
      <ChartHeader>
        <ChartTitle>Muted — both tokens secondary</ChartTitle>
      </ChartHeader>
      <BarList max={chartSum(baseRows)}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='muted' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>

    <Chart>
      <ChartHeader>
        <ChartTitle>Inherit — follows BarListValue color</ChartTitle>
      </ChartHeader>
      <BarList max={chartSum(baseRows)}>
        {baseRows.map(row => (
          <BarListItem key={row.name} value={row.value}>
            <BarListBar />
            <BarListLabel>{row.name}</BarListLabel>
            <BarListValue>
              {formatValue(row.value)}
              <BarListPercent variant='inherit' />
            </BarListValue>
          </BarListItem>
        ))}
      </BarList>
    </Chart>
  </div>
);
```

### Chart

#### Default

The frame with everything it owns — title, hover-revealed actions, and a body slot standing
in for the chart.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const Default = () => (
  <div className='w-400'>
    <Chart data-testid='chart'>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
        <ChartActions>
          <Button variant='ghost' color='neutral' size='small' aria-label='Clear filter'>
            <FilterX />
          </Button>
          <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
            <Settings />
          </Button>
        </ChartActions>
      </ChartHeader>
      <ChartEmpty>chart content</ChartEmpty>
    </Chart>
  </div>
);
```

#### With always visible actions

`alwaysVisible` pins the actions open, which is what a card does while a filter is applied:
the control that clears it must not need hovering to be found.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const WithAlwaysVisibleActions = () => (
  <div className='w-400'>
    <Chart data-testid='chart'>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
        <ChartActions alwaysVisible>
          <Button variant='ghost' color='neutral' size='small' aria-label='Clear filter'>
            <FilterX />
          </Button>
          <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
            <Settings />
          </Button>
        </ChartActions>
      </ChartHeader>
      <ChartEmpty>filtered chart content</ChartEmpty>
    </Chart>
  </div>
);
```

#### Custom size

The card is a full-width block with a minimum height; give it a width and height directly
when a dashboard slot demands a particular size.

```tsx
import { Chart, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const CustomSize = () => (
  <Chart className='w-640 h-320'>
    <ChartHeader>
      <ChartTitle>Custom 640 × 320</ChartTitle>
    </ChartHeader>
    <ChartEmpty>tall chart content</ChartEmpty>
  </Chart>
);
```

#### Long title

`ChartTitle` stays on one line and truncates, so the actions keep their place however long
the title runs.

```tsx
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const LongTitle = () => (
  <div className='w-300'>
    <Chart>
      <ChartHeader>
        <ChartTitle>
          A very long chart title that needs to be truncated so actions remain visible
        </ChartTitle>
        <ChartActions>
          <Button variant='ghost' color='neutral' size='small' aria-label='Clear filter'>
            <FilterX />
          </Button>
          <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
            <Settings />
          </Button>
        </ChartActions>
      </ChartHeader>
      <ChartEmpty>chart content</ChartEmpty>
    </Chart>
  </div>
);
```

#### Empty

`ChartEmpty` centres a default 'No data' in the body — the frame and the title stay, so the
card does not vanish from the grid when its data does.

```tsx
import { Chart, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const Empty = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <ChartEmpty />
    </Chart>
  </div>
);
```

#### Empty with custom message

Pass children to say why it is empty. A card emptied by a filter should say so, since the
fix is different from having no data at all.

```tsx
import { Chart, ChartEmpty, ChartHeader, ChartTitle } from '@wallarm-org/design-system/SimpleCharts';

export const EmptyWithCustomMessage = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <ChartEmpty>No endpoints match the current filter</ChartEmpty>
    </Chart>
  </div>
);
```

### Vertical Stacked Columns Chart

#### Default

Findings by verdict over a week: the legend carries each verdict and its total for the
period, a column per day stacks the verdicts in legend order with the first on top. Hover a
column for the day's breakdown, or a legend item to fade the other verdicts out.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartTooltip, LineChartYAxis, ColumnChart, ColumnChartBody, ColumnChartStack, ColumnChartXAxis } from '@wallarm-org/design-system/SimpleCharts';
import { formatFullNumber } from '@wallarm-org/design-system/utils/abbreviateNumber';

export const Default = () => {
  const { formatDate, formatDateWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-800'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Findings by verdict</ChartTitle>
        </ChartHeader>
        <ColumnChart data={findings} series={verdicts} xKey='timestamp' data-testid='column-chart'>
          <LineChartLegend>
            {verdicts.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                <span className='text-xs font-mono font-medium text-text-primary'>
                  {formatFullNumber(findingsTotals[s.key] ?? 0)}
                </span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <ColumnChartBody>
            <LineChartGrid />
            <ColumnChartXAxis tickFormatter={formatDate} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <ColumnChartStack />
            <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
          </ColumnChartBody>
        </ColumnChart>
      </Chart>
    </div>
  );
};
```

#### Adaptive width

Column width follows the chart width and the number of steps: up to 32px, a fixed 22px
between columns below that, and 16px at least. The same week in a narrow card keeps 32px
columns; two weeks in it narrow them.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartTooltip, LineChartYAxis, ColumnChart, ColumnChartBody, ColumnChartStack, ColumnChartXAxis } from '@wallarm-org/design-system/SimpleCharts';

export const AdaptiveWidth = () => {
  const { formatDate, formatDateWithTimezone } = useChartTimeFormatters();
  return (
    <div className='flex gap-16'>
      <div className='w-428'>
        <Chart>
          <ChartHeader>
            <ChartTitle>7 days</ChartTitle>
          </ChartHeader>
          <ColumnChart
            data={findings}
            series={verdicts}
            xKey='timestamp'
            data-testid='column-chart-week'
          >
            <ColumnChartBody>
              <LineChartGrid />
              <ColumnChartXAxis tickFormatter={formatDate} />
              <LineChartYAxis tickFormatter={formatYTick} />
              <ColumnChartStack />
              <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
            </ColumnChartBody>
          </ColumnChart>
        </Chart>
      </div>
      <div className='w-428'>
        <Chart>
          <ChartHeader>
            <ChartTitle>14 days</ChartTitle>
          </ChartHeader>
          <ColumnChart
            data={findings14}
            series={verdicts}
            xKey='timestamp'
            data-testid='column-chart-two-weeks'
          >
            <ColumnChartBody>
              <LineChartGrid />
              <ColumnChartXAxis tickFormatter={formatDate} />
              <LineChartYAxis tickFormatter={formatYTick} />
              <ColumnChartStack />
              <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
            </ColumnChartBody>
          </ColumnChart>
        </Chart>
      </div>
    </div>
  );
};
```

#### Card height

The plot follows the card height: set a height on `<Chart>` and the columns stretch or
shrink with it. The card goes down to 128px — header, legend and a 72px plot.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartTooltip, LineChartYAxis, ColumnChart, ColumnChartBody, ColumnChartStack, ColumnChartXAxis } from '@wallarm-org/design-system/SimpleCharts';

export const CardHeight = () => {
  const { formatDate, formatDateWithTimezone } = useChartTimeFormatters();
  return (
    <div className='flex w-800 flex-col gap-16'>
      <Chart className='h-128'>
        <ChartHeader>
          <ChartTitle>128px card</ChartTitle>
        </ChartHeader>
        <ColumnChart
          data={findings}
          series={verdicts}
          xKey='timestamp'
          data-testid='column-chart-min'
        >
          <LineChartLegend>
            {verdicts.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <ColumnChartBody>
            <LineChartGrid />
            <ColumnChartXAxis tickFormatter={formatDate} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <ColumnChartStack />
            <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
          </ColumnChartBody>
        </ColumnChart>
      </Chart>
      <Chart className='h-320'>
        <ChartHeader>
          <ChartTitle>320px card</ChartTitle>
        </ChartHeader>
        <ColumnChart
          data={findings}
          series={verdicts}
          xKey='timestamp'
          data-testid='column-chart-tall'
        >
          <LineChartLegend>
            {verdicts.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <ColumnChartBody>
            <LineChartGrid />
            <ColumnChartXAxis tickFormatter={formatDate} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <ColumnChartStack />
            <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
          </ColumnChartBody>
        </ColumnChart>
      </Chart>
    </div>
  );
};
```

#### Clickable legend

Legend items become buttons when they get an `onClick` — here a verdict opens its list, as
on the Agentic Overview. The item's `data-key` carries the series key, so one handler serves
every item. Hover and keyboard focus fade the other verdicts out alike.

```tsx
import { type MouseEvent } from 'react';
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartTooltip, LineChartYAxis, ColumnChart, ColumnChartBody, ColumnChartStack, ColumnChartXAxis } from '@wallarm-org/design-system/SimpleCharts';
import { formatFullNumber } from '@wallarm-org/design-system/utils/abbreviateNumber';

export const ClickableLegend = () => {
  const { formatDate, formatDateWithTimezone } = useChartTimeFormatters();
  const handleLegendClick = (event: MouseEvent<HTMLDivElement>) => {
    openVerdict(event.currentTarget.dataset.key);
  };
  return (
    <div className='w-800'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Click a verdict to open it</ChartTitle>
        </ChartHeader>
        <ColumnChart data={findings} series={verdicts} xKey='timestamp' data-testid='column-chart'>
          <LineChartLegend>
            {verdicts.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key} onClick={handleLegendClick}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                <span className='text-xs font-mono font-medium text-text-primary'>
                  {formatFullNumber(findingsTotals[s.key] ?? 0)}
                </span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <ColumnChartBody>
            <LineChartGrid />
            <ColumnChartXAxis tickFormatter={formatDate} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <ColumnChartStack />
            <LineChartTooltip xTickFormatter={formatDateWithTimezone} />
          </ColumnChartBody>
        </ColumnChart>
      </Chart>
    </div>
  );
};
```

#### Loading

Loading: skeleton legend items over `LineChartEmpty`'s dashed plot frame.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty, LineChartLegend, LineChartLegendItem } from '@wallarm-org/design-system/SimpleCharts';
import { Skeleton } from '@wallarm-org/design-system/Skeleton';

export const Loading = () => (
  <div className='w-800'>
    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Findings by verdict</ChartTitle>
      </ChartHeader>
      <LineChartLegend>
        {verdicts.map(s => (
          <LineChartLegendItem key={s.key} seriesKey={s.key}>
            <Skeleton width='96px' height='16px' rounded={4} />
          </LineChartLegendItem>
        ))}
      </LineChartLegend>
      <LineChartEmpty />
    </Chart>
  </div>
);
```

#### Empty

Empty: `LineChartEmpty` keeps the dashed plot frame and puts the message inside it.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty } from '@wallarm-org/design-system/SimpleCharts';

export const Empty = () => (
  <div className='w-800'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by verdict</ChartTitle>
      </ChartHeader>
      <LineChartEmpty>No findings in this period</LineChartEmpty>
    </Chart>
  </div>
);
```

### HorizontalBarStack

#### Default

The full shape: a headline value with its delta, a three-part band, and the legend that
names the parts.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const Default = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### No delta

The same without the delta — a value with no comparison to make yet.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const NoDelta = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### No value

No header at all: the band and its legend alone, for a card whose total is already stated
somewhere else.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const NoValue = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### With remainder

A `total` above the sum of the parts fills the difference with a grey tail — 91 of 120,
where the 29 nobody has accounted for is part of what the card says.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const WithRemainder = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### Legend off

`legend={false}` leaves the band on its own, for a card too small to carry names or one
whose legend is already nearby.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const LegendOff = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### Palette

All six chart colours in one band, which is the check that they stay tellable apart at the
widths a real breakdown gives them.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const Palette = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStack />
    </Chart>
  </div>
);
```

#### Loading

`HorizontalBarStackSkeleton` stands in while the card loads, holding the header and band
heights so nothing shifts when data arrives.

```tsx
import { Chart, ChartHeader, ChartTitle, HorizontalBarStackSkeleton } from '@wallarm-org/design-system/SimpleCharts';

export const Loading = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Findings by severity</ChartTitle>
      </ChartHeader>
      <HorizontalBarStackSkeleton data-testid='horizontal-bar-stack-skeleton' />
    </Chart>
  </div>
);
```

#### Selectable

`onSelect` turns the legend into a filter — the chosen series stays bright, the rest fade,
and clicking it again clears. Hover always wins, so pointing at any series brings it forward
regardless of what is selected.

```tsx
import { useState } from 'react';
import { Chart, ChartHeader, ChartTitle, MetricHeader, MetricValue, HorizontalBarStack } from '@wallarm-org/design-system/SimpleCharts';

export const Selectable = () => {
  const [selected, setSelected] = useState<string | null>('Critical');
  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Findings by severity</ChartTitle>
        </ChartHeader>
        <HorizontalBarStack
          data-testid='horizontal-bar-stack'
          data={severityData}
          selectedNames={selected ? [selected] : []}
          onSelect={name => setSelected(prev => (prev === name ? null : name))}
        >
          <MetricHeader>
            <MetricValue>91</MetricValue>
          </MetricHeader>
        </HorizontalBarStack>
      </Chart>
    </div>
  );
};
```

### LineChart

#### Default

One series with the full chrome — grid, both axes, and a tooltip that follows the pointer
along the line.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, singleSeries } from './lib/sampleData';

export const Default = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-560'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Requests per hour</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={singleSeries} xKey='timestamp'>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <LineChartLine seriesKey='requests' curve='linear' />
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Default multi

Three series with a legend composed from `LineChartLegendItem` rows. The dot in each row is
the same one the tooltip uses, so the colours cannot drift apart.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from './lib/sampleData';

export const DefaultMulti = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-560'>
      <Chart data-testid='chart'>
        <ChartHeader>
          <ChartTitle>Traffic, errors, and latency</ChartTitle>
        </ChartHeader>
        <LineChart
          data-testid='line-chart'
          data={hourlyData24}
          series={multiSeries}
          xKey='timestamp'
        >
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### With metric

The metric variant: the shared `Metric` bricks sit to the left of the legend in a row of
their own between the header and the plot. Pure composition — the chart is untouched and the
card simply grows by that row.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, MetricDelta, MetricHeader, MetricValue, LineChart, LineChartBody, LineChartGrid, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from './lib/sampleData';

export const WithMetric = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-800'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Requests per hour</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <div className='flex items-center justify-between pr-8'>
            <MetricHeader className='px-16'>
              <MetricValue>{2903}</MetricValue>
              <MetricDelta value={10} trend='up' sentiment='negative' />
            </MetricHeader>
            <MultiLegend />
          </div>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Curves

Straight joins tell the truth about where the samples are; `monotone` smooths between them
and reads better for a rate. Mix the two only when the series mean genuinely different
things.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyData24, multiSeries } from './lib/sampleData';

export const Curves = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='grid grid-cols-2 gap-16 w-1120'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Linear interpolation</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <MultiLegend />
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} curve='linear' />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Mixed curves — monotone vs linear</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <MultiLegend />
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <LineChartLine seriesKey='requests' curve='monotone' />
            <LineChartLine seriesKey='errors' curve='linear' />
            <LineChartLine seriesKey='latency' curve='linear' />
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Line styling

A dashed series against a solid one — the way to separate a threshold or a projection from
measured data — and a CSS colour string for a series whose colour is decided elsewhere.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { customColorSeries, dashedSeries, hourlyData24 } from './lib/sampleData';

export const LineStyling = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='grid grid-cols-2 gap-16 w-1120'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Solid + dashed series</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={dashedSeries} xKey='timestamp'>
          <MultiLegend series={dashedSeries} />
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {dashedSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Custom palette via CSS color string</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={customColorSeries} xKey='timestamp'>
          <MultiLegend series={customColorSeries} />
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {customColorSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Edge cases

The three shapes that break naive charts: a sparkline with no chrome at all, a single data
point, and a series with null gaps, which has to break the line rather than bridge it.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { dataWithErrorGaps, hourlyData24, multiSeries, singlePointData, singleSeries } from './lib/sampleData';

export const EdgeCases = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='grid grid-cols-2 gap-16 w-1120'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Sparkline — no chrome</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={singleSeries} xKey='timestamp'>
          <LineChartBody>
            <LineChartLine seriesKey='requests' />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Single data point</ChartTitle>
        </ChartHeader>
        <LineChart data={singlePointData} series={singleSeries} xKey='timestamp'>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} />
            <LineChartYAxis tickFormatter={formatYTick} />
            <LineChartLine seriesKey='requests' />
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Series with null gaps</ChartTitle>
        </ChartHeader>
        <LineChart data={dataWithErrorGaps} series={multiSeries} xKey='timestamp'>
          <MultiLegend />
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Custom tooltip

Composing the hover popover yourself, a `LineChartHoverPopoverRow` per series, for when a
value needs its unit rather than the default name-and-number.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartHoverPopover, LineChartHoverPopoverDot, LineChartHoverPopoverRow, LineChartHoverPopoverTimestamp, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { formatFullNumber } from '@wallarm-org/design-system/utils/abbreviateNumber';
import { hourlyData24, multiSeries, unitsByKey } from './lib/sampleData';

export const CustomTooltip = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='w-560'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Custom tooltip with units</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip>
              {({ rows, xValue }) => (
                <LineChartHoverPopover>
                  <LineChartHoverPopoverTimestamp>
                    {formatHourWithTimezone(xValue)}
                  </LineChartHoverPopoverTimestamp>
                  {rows.map(({ series: s, value: raw }) => {
                    const value = typeof raw === 'number' ? raw : 0;
                    const unit = unitsByKey[s.key] ?? '';
                    return (
                      <LineChartHoverPopoverRow
                        key={s.key}
                        series={s}
                        value={value}
                        formatValue={v =>
                          `${typeof v === 'number' ? formatFullNumber(v) : String(v ?? '')}${unit}`
                        }
                      />
                    );
                  })}
                </LineChartHoverPopover>
              )}
            </LineChartTooltip>
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Legend placements

Legend placement is structural rather than a prop: JSX order picks top or bottom, and
wrapping the body and the legend in an `HStack` picks left or right, where a vertical
orientation stacks its rows.

```tsx
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { HStack } from '@wallarm-org/design-system/Stack';
import { hourlyData24, multiSeries } from './lib/sampleData';

export const LegendPlacements = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  return (
    <div className='grid grid-cols-2 gap-16 w-1120'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top — JSX order</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Bottom — JSX order</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Left — wrapped in HStack</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <HStack flexGrow gap={12} align='stretch'>
            <LineChartLegend orientation='vertical'>
              {multiSeries.map(s => (
                <LineChartLegendItem key={s.key} seriesKey={s.key}>
                  <LineChartHoverPopoverDot color={s.color} />
                  <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                </LineChartLegendItem>
              ))}
            </LineChartLegend>
            <LineChartBody>
              <LineChartGrid />
              <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
              <LineChartYAxis tickFormatter={formatYTick} />
              {multiSeries.map(s => (
                <LineChartLine key={s.key} seriesKey={s.key} />
              ))}
              <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
            </LineChartBody>
          </HStack>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Right — wrapped in HStack</ChartTitle>
        </ChartHeader>
        <LineChart data={hourlyData24} series={multiSeries} xKey='timestamp'>
          <HStack flexGrow gap={12} align='stretch'>
            <LineChartBody>
              <LineChartGrid />
              <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
              <LineChartYAxis tickFormatter={formatYTick} />
              {multiSeries.map(s => (
                <LineChartLine key={s.key} seriesKey={s.key} />
              ))}
              <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
            </LineChartBody>
            <LineChartLegend orientation='vertical'>
              {multiSeries.map(s => (
                <LineChartLegendItem key={s.key} seriesKey={s.key}>
                  <LineChartHoverPopoverDot color={s.color} />
                  <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                </LineChartLegendItem>
              ))}
            </LineChartLegend>
          </HStack>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Filterable

Clicking a legend row isolates that series and clicking another adds it back, with the
header's clear control appearing while anything is hidden.

```tsx
import { useState } from 'react';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';
import { hourlyData24, multiSeries } from './lib/sampleData';

export const Filterable = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  const [hidden, setHidden] = useState<string[]>([]);
  // First click on a fully-visible chart isolates the clicked series (hides
  // every other one); after that, clicks toggle individual series in and out.
  const toggle = (key: string) => {
    setHidden(prev => {
      if (prev.length === 0) return multiSeries.filter(s => s.key !== key).map(s => s.key);
      if (prev.includes(key)) return prev.filter(k => k !== key);
      return [...prev, key];
    });
  };
  const filtered = hidden.length > 0;

  return (
    <div className='w-560'>
      <Chart data-testid='chart'>
        <ChartHeader>
          <ChartTitle>Click a row to isolate, click another to add</ChartTitle>
          <ChartActions alwaysVisible={filtered}>
            {filtered && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant='ghost'
                    color='neutral'
                    size='small'
                    aria-label='Clear filter'
                    onClick={() => setHidden([])}
                  >
                    <FilterX />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Remove filter</TooltipContent>
              </Tooltip>
            )}
          </ChartActions>
        </ChartHeader>
        <LineChart
          data-testid='line-chart'
          data={hourlyData24}
          series={multiSeries}
          xKey='timestamp'
          filteredKeys={hidden}
        >
          <LineChartLegend>
            {multiSeries.map(s => (
              <Tooltip key={s.key}>
                <TooltipTrigger asChild>
                  <LineChartLegendItem seriesKey={s.key} onClick={() => toggle(s.key)}>
                    <LineChartHoverPopoverDot color={s.color} />
                    <span className='text-xs font-mono text-text-primary'>{s.label}</span>
                  </LineChartLegendItem>
                </TooltipTrigger>
                <TooltipContent>
                  {hidden.includes(s.key) ? 'Remove filter' : 'Click to filter'}
                </TooltipContent>
              </Tooltip>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Cross chart hover sync

Two cards sharing a pointer, and it takes two mechanisms: `syncId` lines up the cursor and
tooltip through recharts, while `activeKey` shares the series highlight through our own
context.

```tsx
import { useState } from 'react';
import { Chart, ChartHeader, ChartTitle, useChartTimeFormatters, LineChart, LineChartBody, LineChartGrid, LineChartHoverPopoverDot, LineChartLegend, LineChartLegendItem, LineChartLine, LineChartTooltip, LineChartXAxis, LineChartYAxis } from '@wallarm-org/design-system/SimpleCharts';
import { hourlyDataA, hourlyDataB, multiSeries } from './lib/sampleData';

export const CrossChartHoverSync = () => {
  const { formatHour, formatHourWithTimezone } = useChartTimeFormatters();
  // `syncId` syncs the *cursor X* (tooltip + brush) via recharts' own redux
  // middleware. `activeKey` + `onActiveKeyChange` sync the *series highlight*
  // (line dimming + legend hover) via our context. The two pair cleanly —
  // each owns the surface it controls and neither reinvents the other.
  const [activeKey, setActiveKey] = useState<string | null>(null);

  return (
    <div className='grid grid-cols-2 gap-16 w-1120'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Region A</ChartTitle>
        </ChartHeader>
        <LineChart
          data={hourlyDataA}
          series={multiSeries}
          xKey='timestamp'
          syncId='regions'
          activeKey={activeKey}
          onActiveKeyChange={setActiveKey}
        >
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>

      <Chart>
        <ChartHeader>
          <ChartTitle>Region B</ChartTitle>
        </ChartHeader>
        <LineChart
          data={hourlyDataB}
          series={multiSeries}
          xKey='timestamp'
          syncId='regions'
          activeKey={activeKey}
          onActiveKeyChange={setActiveKey}
        >
          <LineChartLegend>
            {multiSeries.map(s => (
              <LineChartLegendItem key={s.key} seriesKey={s.key}>
                <LineChartHoverPopoverDot color={s.color} />
                <span className='text-xs font-mono text-text-primary'>{s.label}</span>
              </LineChartLegendItem>
            ))}
          </LineChartLegend>
          <LineChartBody>
            <LineChartGrid />
            <LineChartXAxis tickFormatter={formatHour} minTickGap={32} />
            <LineChartYAxis tickFormatter={formatYTick} />
            {multiSeries.map(s => (
              <LineChartLine key={s.key} seriesKey={s.key} />
            ))}
            <LineChartTooltip xTickFormatter={formatHourWithTimezone} />
          </LineChartBody>
        </LineChart>
      </Chart>
    </div>
  );
};
```

#### Zoom

Drag across the plot to choose a range, then confirm in the popover — Enter or the button
emits `onZoomChange`, while Escape, an outside click or a new drag dismisses it. Slicing the
data to that range is yours, and so is the way back out.

```tsx
export const Zoom = () => (
  <div className='w-560'>
    <ZoomControlledChart />
  </div>
);
```

#### Loading

There is no `loading` prop: the state is composed from the same primitives as a populated
chart — `Skeleton` chips inside the legend and a bare `LineChartEmpty` for the dashed plot —
with `aria-busy` on the `Chart` left to the caller.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty } from '@wallarm-org/design-system/SimpleCharts';
import { HStack } from '@wallarm-org/design-system/Stack';

export const Loading = () => (
  <div className='grid grid-cols-2 gap-16 w-1120'>
    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>No legend</ChartTitle>
      </ChartHeader>
      <LineChartEmpty />
    </Chart>

    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Top — JSX order</ChartTitle>
      </ChartHeader>
      <LoadingLegend />
      <LineChartEmpty />
    </Chart>

    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Bottom — JSX order</ChartTitle>
      </ChartHeader>
      <LineChartEmpty />
      <LoadingLegend />
    </Chart>

    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Left — wrapped in HStack</ChartTitle>
      </ChartHeader>
      <HStack flexGrow gap={12} align='stretch'>
        <LoadingLegend orientation='vertical' />
        <LineChartEmpty className='flex-1 min-w-0' />
      </HStack>
    </Chart>

    <Chart aria-busy='true' aria-live='polite'>
      <ChartHeader>
        <ChartTitle>Right — wrapped in HStack</ChartTitle>
      </ChartHeader>
      <HStack flexGrow gap={12} align='stretch'>
        <LineChartEmpty className='flex-1 min-w-0' />
        <LoadingLegend orientation='vertical' />
      </HStack>
    </Chart>
  </div>
);
```

#### Refreshing

Each panel loads for two seconds before swapping to data, and the refresh button replays it.
The skeleton and the real chart share an outer layout, so nothing but the content moves on
the swap.

```tsx
import { HStack } from '@wallarm-org/design-system/Stack';

export const Refreshing = () => (
  <div className='grid grid-cols-2 gap-16 w-1120'>
    <RefreshingChart placement='none' title='No legend' />
    <RefreshingChart placement='top' title='Top — JSX order' />
    <RefreshingChart placement='bottom' title='Bottom — JSX order' />
    <RefreshingChart placement='left' title='Left — wrapped in HStack' />
    <RefreshingChart placement='right' title='Right — wrapped in HStack' />
  </div>
);
```

#### Empty

`LineChartEmpty` keeps the dashed plot frame and puts the message inside it, so a card with
no data still reads as a chart rather than as something broken.

```tsx
import { Chart, ChartHeader, ChartTitle, LineChartEmpty } from '@wallarm-org/design-system/SimpleCharts';

export const Empty = () => (
  <div className='w-560'>
    <Chart>
      <ChartHeader>
        <ChartTitle>No data</ChartTitle>
      </ChartHeader>
      <LineChartEmpty>No data</LineChartEmpty>
    </Chart>
  </div>
);
```

#### Long time range

A thousand hourly samples in one card: drag to zoom and the header's control restores the
full range. The story slices the data itself, exactly as a consumer has to.

```tsx
export const LongTimeRange = () => (
  <div className='w-720'>
    <LongTimeRangeChart />
  </div>
);
```

### Metric

#### Gallery

Every brick combination on its own card, mirroring the Figma options board: value alone,
value with a delta in each sentiment, and the three `MetricTotal` connectors: a slash, the
word "of", and the word "total" after the number.

```tsx
import { Metric, MetricCaption, MetricDelta, MetricHeader, MetricTotal, MetricValue } from '@wallarm-org/design-system/SimpleCharts';

export const Gallery = () => (
  <div className='flex flex-wrap gap-16'>
    <Card title='Value only'>
      <Metric data-testid='metric'>
        <MetricHeader>
          <MetricValue>91</MetricValue>
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Negative — count rose'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Positive — count fell'>
      <Metric>
        <MetricHeader>
          <MetricValue>74</MetricValue>
          <MetricDelta value={8} trend='down' sentiment='positive' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Neutral'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricDelta value={10} trend='up' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Total — slash'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricTotal connector='slash'>120</MetricTotal>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Total — of'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricTotal connector='of'>120</MetricTotal>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='Total — total'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricTotal connector='total'>120</MetricTotal>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
      </Metric>
    </Card>

    <Card title='With caption'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
        <MetricCaption>blocked today</MetricCaption>
      </Metric>
    </Card>

    <Card title='Everything'>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricTotal connector='of'>120</MetricTotal>
          <MetricDelta value={10} trend='up' sentiment='negative' />
        </MetricHeader>
        <MetricCaption>blocked today</MetricCaption>
      </Metric>
    </Card>
  </div>
);
```

#### Loading

`MetricSkeleton` in place of the stat while the card loads, so the number arriving does not
resize the card.

```tsx
import { MetricSkeleton } from '@wallarm-org/design-system/SimpleCharts';

export const Loading = () => (
  <Card title='Findings'>
    <MetricSkeleton data-testid='metric-skeleton' />
  </Card>
);
```

#### Sparkline

`MetricSparkline` after `Metric` draws the trend over the period, edge to edge along the
card's bottom. Hover it for a ruler on the nearest point and a popover with its date and value.

```tsx
import { Chart, ChartHeader, ChartTitle, Metric, MetricCaption, MetricDelta, MetricHeader, MetricSparkline, MetricValue } from '@wallarm-org/design-system/SimpleCharts';

export const Sparkline = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Attacks</ChartTitle>
      </ChartHeader>
      <Metric>
        <MetricHeader>
          <MetricValue>91</MetricValue>
          <MetricDelta value={10} trend='up' sentiment='positive' />
        </MetricHeader>
        <MetricCaption>last 9 days</MetricCaption>
      </Metric>
      <MetricSparkline data-testid='sparkline' data={attacks} label='Attacks' />
    </Chart>
  </div>
);
```

#### Sparkline colors

The sparkline's `color` is set per chart, on purpose apart from the delta's `sentiment`:
`brand` (default), `positive`, `negative`, and `neutral`.

```tsx
import { Chart, ChartHeader, ChartTitle, Metric, MetricCaption, MetricDelta, MetricHeader, MetricSparkline, MetricValue } from '@wallarm-org/design-system/SimpleCharts';

export const SparklineColors = () => (
  <div className='flex flex-wrap gap-16'>
    <div className='w-256'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Negative</ChartTitle>
        </ChartHeader>
        <Metric>
          <MetricHeader>
            <MetricValue>74</MetricValue>
            <MetricDelta value={5} trend='down' sentiment='negative' />
          </MetricHeader>
          <MetricCaption>last 9 days</MetricCaption>
        </Metric>
        <MetricSparkline data={attacks} color='negative' label='Attacks' />
      </Chart>
    </div>
    <div className='w-256'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Positive</ChartTitle>
        </ChartHeader>
        <Metric>
          <MetricHeader>
            <MetricValue>91</MetricValue>
            <MetricDelta value={10} trend='up' sentiment='positive' />
          </MetricHeader>
          <MetricCaption>last 9 days</MetricCaption>
        </Metric>
        <MetricSparkline data={attacks} color='positive' label='Attacks' />
      </Chart>
    </div>
    <div className='w-256'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Brand</ChartTitle>
        </ChartHeader>
        <Metric>
          <MetricHeader>
            <MetricValue>91</MetricValue>
            <MetricDelta value={10} trend='up' sentiment='positive' />
          </MetricHeader>
          <MetricCaption>last 9 days</MetricCaption>
        </Metric>
        <MetricSparkline data={attacks} label='Attacks' />
      </Chart>
    </div>
    <div className='w-256'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Neutral</ChartTitle>
        </ChartHeader>
        <Metric>
          <MetricHeader>
            <MetricValue>91</MetricValue>
            <MetricDelta value={10} trend='up' sentiment='positive' />
          </MetricHeader>
          <MetricCaption>last 9 days</MetricCaption>
        </Metric>
        <MetricSparkline data={attacks} color='neutral' label='Attacks' />
      </Chart>
    </div>
  </div>
);
```

### Overview

#### Default

One card per chart, at its default: a `BarList` top-five, a `PieChart` share-of-total, a
`LineChart` over time, a `HorizontalBarStack` composition and a bare `Metric`.

```tsx
export const Default = () => (
  <div className='flex flex-col gap-16 w-832'>
    <div className='grid grid-cols-2 gap-16'>
      <BarChartCard />
      <PieChartCard />
    </div>
    <LineChartCard />
    <div className='grid grid-cols-2 gap-16'>
      <HorizontalBarStackCard />
      <MetricCard />
    </div>
  </div>
);
```

### PieChart

#### Default

The interactive shape: click a legend row to filter to that slice, with the header's clear
control appearing while the filter holds.

```tsx
import { useMemo, useState } from 'react';
import { Badge } from '@wallarm-org/design-system/Badge';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const Default = () => {
  const [filtered, setFiltered] = useState<string | null>(null);
  const visibleRows = useMemo(
    () => (filtered ? baseRows.filter(r => r.name === filtered) : baseRows),
    [filtered],
  );
  const total = baseRows.reduce((sum, r) => sum + r.value, 0);
  const visibleTotal = visibleRows.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
          <ChartActions alwaysVisible={filtered !== null}>
            {filtered !== null && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant='ghost'
                    color='neutral'
                    size='small'
                    aria-label='Clear filter'
                    onClick={() => setFiltered(null)}
                  >
                    <FilterX />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Remove filter</TooltipContent>
              </Tooltip>
            )}
            <Tooltip>
              <TooltipTrigger asChild>
                <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
                  <Settings />
                </Button>
              </TooltipTrigger>
              <TooltipContent>Change data source</TooltipContent>
            </Tooltip>
          </ChartActions>
        </ChartHeader>
        <PieChart data-testid='pie-chart' data={visibleRows} total={visibleTotal}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue formatHoveredValue={d => formatValue(d.value)}>
                {formatValue(filtered ? visibleTotal : total)}
              </PieChartCenterValue>
              <PieChartCenterLabel
                className='whitespace-nowrap'
                pluralize={{ one: 'request', other: 'requests' }}
              />
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {visibleRows.map(row => (
              <Tooltip key={row.name}>
                <TooltipTrigger asChild>
                  <PieChartLegendItem
                    name={row.name}
                    selected={filtered === row.name}
                    onClick={() => setFiltered(filtered === row.name ? null : row.name)}
                  >
                    <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                      {row.name}
                    </Badge>
                    <PieChartLegendValue>
                      {formatValue(row.value)}
                      <LegendDot />
                      <PieChartLegendPercent />
                    </PieChartLegendValue>
                  </PieChartLegendItem>
                </TooltipTrigger>
                <TooltipContent>
                  {filtered === row.name ? 'Click to remove filter' : 'Click to filter'}
                </TooltipContent>
              </Tooltip>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Selectable

Selection kept in state rather than by filtering the data — the chosen row stays lit and the
other slices fade, so the whole remains visible while one part is emphasised.

```tsx
import { useMemo, useState } from 'react';
import { Badge } from '@wallarm-org/design-system/Badge';
import { Button } from '@wallarm-org/design-system/Button';
import { FilterX } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const Selectable = () => {
  const [selected, setSelected] = useState<Set<string>>(() => new Set(['4XX']));
  const total = baseRows.reduce((sum, r) => sum + r.value, 0);
  const selectedNames = useMemo(() => Array.from(selected), [selected]);

  const toggle = (name: string) => {
    setSelected(prev => {
      const next = new Set(prev);
      if (next.has(name)) next.delete(name);
      else next.add(name);
      return next;
    });
  };

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
          <ChartActions alwaysVisible={selected.size > 0}>
            {selected.size > 0 && (
              <Tooltip>
                <TooltipTrigger asChild>
                  <Button
                    variant='ghost'
                    color='neutral'
                    size='small'
                    aria-label='Clear selection'
                    onClick={() => setSelected(new Set())}
                  >
                    <FilterX />
                  </Button>
                </TooltipTrigger>
                <TooltipContent>Clear selection</TooltipContent>
              </Tooltip>
            )}
          </ChartActions>
        </ChartHeader>
        <PieChart
          data-testid='pie-chart'
          data={baseRows}
          total={total}
          selectedNames={selectedNames}
        >
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {baseRows.map(row => (
              <Tooltip key={row.name}>
                <TooltipTrigger asChild>
                  <PieChartLegendItem name={row.name} onClick={() => toggle(row.name)}>
                    <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                      {row.name}
                    </Badge>
                    <PieChartLegendValue>
                      {formatValue(row.value)}
                      <LegendDot />
                      <PieChartLegendPercent />
                    </PieChartLegendValue>
                  </PieChartLegendItem>
                </TooltipTrigger>
                <TooltipContent>
                  {selected.has(row.name) ? 'Click to deselect' : 'Click to select'}
                </TooltipContent>
              </Tooltip>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Truncated labels

Legend labels truncate at the row width, since the legend takes whatever horizontal space
the donut leaves.

```tsx
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';

export const TruncatedLabels = () => {
  const total = longLabelRows.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
        </ChartHeader>
        <PieChart data={longLabelRows} total={total}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {longLabelRows.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <Tooltip>
                  <TooltipTrigger asChild>
                    <span className='min-w-0 flex-1 truncate text-xs font-mono text-text-primary pointer-events-auto'>
                      {row.name}
                    </span>
                  </TooltipTrigger>
                  <TooltipContent>{row.name}</TooltipContent>
                </Tooltip>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Truncated labels with tooltip

The same rows under `OverflowTooltip`, which reveals the full label only when it is actually
cut off.

```tsx
import { OverflowTooltip, OverflowTooltipContent, OverflowTooltipTrigger } from '@wallarm-org/design-system/OverflowTooltip';
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const TruncatedLabelsWithTooltip = () => {
  const total = longLabelRows.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
        </ChartHeader>
        <PieChart data={longLabelRows} total={total}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {longLabelRows.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <OverflowTooltip>
                  <OverflowTooltipTrigger>
                    <span className='min-w-0 flex-1 truncate text-xs font-mono text-text-primary pointer-events-auto'>
                      {row.name}
                    </span>
                  </OverflowTooltipTrigger>
                  <OverflowTooltipContent>{row.name}</OverflowTooltipContent>
                </OverflowTooltip>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Loading

`PieChartSkeleton` takes a row count so the placeholder legend is as long as the real one,
and the card does not resize when data lands.

```tsx
import { Chart, ChartHeader, ChartTitle, PieChartSkeleton } from '@wallarm-org/design-system/SimpleCharts';

export const Loading = () => (
  <div className='w-400'>
    <Chart>
      <ChartHeader>
        <ChartTitle>Top 5 Endpoints</ChartTitle>
      </ChartHeader>
      <PieChartSkeleton data-testid='pie-chart-skeleton' rows={5} />
    </Chart>
  </div>
);
```

#### Single slice

One slice is a full ring at 100% — legible, but ask whether a `Metric` says it better, since
there is no share left to compare against.

```tsx
import { Badge } from '@wallarm-org/design-system/Badge';
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const SingleSlice = () => {
  const data: Row[] = [{ name: '5XX', value: 23, color: 'red', badgeColor: 'red' }];
  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints</ChartTitle>
        </ChartHeader>
        <PieChart data-testid='pie-chart' data={data}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>23</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {data.map(row => (
              <PieChartLegendItem key={row.name} name={row.name} selected>
                <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                  {row.name}
                </Badge>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Two slices

Two slices is where a donut earns its place: the split is readable at a glance without
reading either number.

```tsx
import { Badge } from '@wallarm-org/design-system/Badge';
import { Chart, ChartHeader, ChartTitle, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const TwoSlices = () => {
  const data: Row[] = [
    { name: 'Success', value: 78, color: 'green', badgeColor: 'green' },
    { name: 'Errors', value: 22, color: 'red', badgeColor: 'red' },
  ];
  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Response status — values only</ChartTitle>
        </ChartHeader>
        <PieChart data-testid='pie-chart' data={data} total={100}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>100</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {data.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                  {row.name}
                </Badge>
                <PieChartLegendValue>{formatValue(row.value)}</PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Custom colors

Colours passed per datum rather than taken from the palette, for a breakdown whose
categories already have colours elsewhere in the product.

```tsx
import { Badge } from '@wallarm-org/design-system/Badge';
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, type PieChartDatum, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const CustomColors = () => {
  const data: PieChartDatum[] = customRows.map(r => ({
    name: r.name,
    value: r.value,
    className: r.fillClass,
  }));
  const total = customRows.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints (custom palette)</ChartTitle>
        </ChartHeader>
        <PieChart data={data} total={total}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {customRows.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                  {row.name}
                </Badge>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Zero total

Every value zero: the ring renders empty and the percents read 0% rather than the chart
dividing by nothing or disappearing.

```tsx
import { Badge } from '@wallarm-org/design-system/Badge';
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const ZeroTotal = () => {
  const data: Row[] = baseRows.map(r => ({ ...r, value: 0 }));
  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Top 5 Endpoints (no traffic)</ChartTitle>
        </ChartHeader>
        <PieChart data-testid='pie-chart' data={data}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>0</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {data.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                  {row.name}
                </Badge>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Width variants

The same chart at 280, 400 and 560px. The donut holds its size and the legend takes the
rest, which is what sets the practical minimum width.

```tsx
import { useState } from 'react';
import { Badge } from '@wallarm-org/design-system/Badge';
import { Button } from '@wallarm-org/design-system/Button';
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuItemIcon, DropdownMenuLabel, DropdownMenuTrigger } from '@wallarm-org/design-system/DropdownMenu';
import { Check, Settings } from '@wallarm-org/design-system/icons';
import { Chart, ChartActions, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';
import { Tooltip, TooltipContent, TooltipTrigger } from '@wallarm-org/design-system/Tooltip';
import { cn } from '@wallarm-org/design-system/utils/cn';

export const WidthVariants = () => {
  const [key, setKey] = useState<WidthKey>('wide');
  const [menuOpen, setMenuOpen] = useState(false);
  const current = widthOptions[key];
  const total = baseRows.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className={current.className}>
      <Chart>
        <ChartHeader>
          <ChartTitle>{current.title}</ChartTitle>
          <ChartActions alwaysVisible={menuOpen}>
            <Tooltip disabled={menuOpen}>
              <TooltipTrigger asChild>
                <span className='inline-flex'>
                  <DropdownMenu onOpenChange={setMenuOpen}>
                    <DropdownMenuTrigger asChild>
                      <Button variant='ghost' color='neutral' size='small' aria-label='Settings'>
                        <Settings />
                      </Button>
                    </DropdownMenuTrigger>
                    <DropdownMenuContent>
                      <DropdownMenuLabel>Container width</DropdownMenuLabel>
                      <DropdownMenuGroup>
                        {(Object.keys(widthOptions) as WidthKey[]).map(k => (
                          <DropdownMenuItem key={k} onSelect={() => setKey(k)}>
                            <span className='flex-1'>{widthOptions[k].title}</span>
                            <DropdownMenuItemIcon>
                              <Check className={cn(key !== k && 'opacity-0')} />
                            </DropdownMenuItemIcon>
                          </DropdownMenuItem>
                        ))}
                      </DropdownMenuGroup>
                    </DropdownMenuContent>
                  </DropdownMenu>
                </span>
              </TooltipTrigger>
              <TooltipContent>Change container width</TooltipContent>
            </Tooltip>
          </ChartActions>
        </ChartHeader>
        <PieChart data={baseRows} total={total}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {baseRows.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                  {row.name}
                </Badge>
                <PieChartLegendValue>
                  {formatValue(row.value)}
                  <LegendDot />
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

#### Percent variants

The three percent treatments, matching `BarList` — `split` colours number and symbol
differently, `muted` sets both back, `inherit` leaves them to the row.

```tsx
import { Badge } from '@wallarm-org/design-system/Badge';
import { Chart, ChartHeader, ChartTitle, LegendDot, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const PercentVariants = () => {
  const total = baseRows.reduce((sum, r) => sum + r.value, 0);

  const renderChart = (variant: 'split' | 'muted' | 'inherit', title: string) => (
    <Chart>
      <ChartHeader>
        <ChartTitle>{title}</ChartTitle>
      </ChartHeader>
      <PieChart data={baseRows} total={total}>
        <PieChartDonut>
          <PieChartCenter>
            <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
            <PieChartCenterLabel className='whitespace-nowrap'>requests</PieChartCenterLabel>
          </PieChartCenter>
        </PieChartDonut>
        <PieChartLegend>
          {baseRows.map(row => (
            <PieChartLegendItem key={row.name} name={row.name}>
              <Badge color={row.badgeColor} type='secondary' textVariant='code'>
                {row.name}
              </Badge>
              <PieChartLegendValue>
                {formatValue(row.value)}
                <LegendDot />
                <PieChartLegendPercent variant={variant} />
              </PieChartLegendValue>
            </PieChartLegendItem>
          ))}
        </PieChartLegend>
      </PieChart>
    </Chart>
  );

  return (
    <div className='flex flex-col gap-16 w-400'>
      {renderChart('split', 'Split — value primary, % secondary (default)')}
      {renderChart('muted', 'Muted — both tokens secondary')}
      {renderChart('inherit', 'Inherit — follows PieChartLegendValue color')}
    </div>
  );
};
```

#### Palette

The six chart colours around one ring, for checking adjacent slices stay tellable apart at
small sizes.

```tsx
import { Chart, ChartHeader, ChartTitle, PieChart, PieChartCenter, PieChartCenterLabel, PieChartCenterValue, type PieChartDatum, PieChartDonut, PieChartLegend, PieChartLegendItem, PieChartLegendPercent, PieChartLegendValue } from '@wallarm-org/design-system/SimpleCharts';

export const Palette = () => {
  const data: PieChartDatum[] = PALETTE.slice(0, 6).map((color, i) => ({
    name: color,
    value: 10 + i,
    color,
  }));
  const total = data.reduce((sum, r) => sum + r.value, 0);

  return (
    <div className='w-400'>
      <Chart>
        <ChartHeader>
          <ChartTitle>Built-in palette — percents only</ChartTitle>
        </ChartHeader>
        <PieChart data={data} total={total}>
          <PieChartDonut>
            <PieChartCenter>
              <PieChartCenterValue>{formatValue(total)}</PieChartCenterValue>
              <PieChartCenterLabel>total</PieChartCenterLabel>
            </PieChartCenter>
          </PieChartDonut>
          <PieChartLegend>
            {data.map(row => (
              <PieChartLegendItem key={row.name} name={row.name}>
                <span className='inline-flex items-center gap-6 text-xs font-mono text-text-primary capitalize'>
                  <span
                    aria-hidden
                    className='inline-block size-8 rounded-2'
                    style={{
                      backgroundColor: `var(--color-${row.color === 'slate' ? 'badge-slate-dark-alt' : row.color === 'brand' ? 'w-orange-500' : `${row.color}-500`})`,
                    }}
                  />
                  {row.name}
                </span>
                <PieChartLegendValue>
                  <PieChartLegendPercent />
                </PieChartLegendValue>
              </PieChartLegendItem>
            ))}
          </PieChartLegend>
        </PieChart>
      </Chart>
    </div>
  );
};
```

## Props

### AreaChartArea

| Prop             | Type                                  | Default             | Description                                                                    |
| ---------------- | ------------------------------------- | ------------------- | ------------------------------------------------------------------------------ |
| seriesKey \*     | `string`                              |                     | Joins to `LineChartSeries.key` from the root `series` prop.                    |
| curve            | `"linear" \| "monotone" \| undefined` | `monotone`          | Recharts curve type. Defaults to `'monotone'`.                                 |
| disableAnimation | `boolean \| undefined`                | `false`             | Force-disable the recharts mount animation.                                    |
| connectNulls     | `boolean \| undefined`                | `false`             | Recharts pass-through — when `true`, the area bridges `null`/`undefined` gaps. |
| strokeWidth      | `number \| undefined`                 | `AREA_STROKE_WIDTH` | Stroke width override. Defaults to `AREA_STROKE_WIDTH`.                        |

### AreaChartBody

| Prop           | Type                                                 | Default               | Description                                              |
| -------------- | ---------------------------------------------------- | --------------------- | -------------------------------------------------------- |
| height         | `number \| undefined`                                | `DEFAULT_BODY_HEIGHT` | Body height passed to recharts' `<ResponsiveContainer>`. |
| defaultChecked | `boolean \| undefined`                               |                       |                                                          |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |                       |                                                          |
| autoFocus      | `boolean \| undefined`                               |                       |                                                          |
| id             | `string \| undefined`                                |                       |                                                          |
| tabIndex       | `number \| undefined`                                |                       |                                                          |
| title          | `string \| undefined`                                |                       |                                                          |
| rel            | `string \| undefined`                                |                       |                                                          |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |                       |                                                          |

### AreaChart

| Prop              | Type                                                         | Default | Description                                                                                                                                                                            |
| ----------------- | ------------------------------------------------------------ | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data \*           | `T[]`                                                        |         | Long-form data array, one entry per X position.                                                                                                                                        |
| series \*         | `LineChartSeries<Extract<keyof T, string>>[]`                |         | Schema describing each area drawn from `data`.                                                                                                                                         |
| xKey \*           | `Extract<keyof T, string>`                                   |         | Key on each datum used as the X-axis value.                                                                                                                                            |
| variant           | `AreaChartVariant \| undefined`                              |         | Area chart variant. - `'stacked'` (default): series stack cumulatively — each band starts where the previous ends. - `'standard'`: series overlap from the baseline with transparency. |
| activeKey         | `string \| null \| undefined`                                |         | Controlled hover key — pass alongside `onActiveKeyChange` for cross-chart sync.                                                                                                        |
| onActiveKeyChange | `((key: string \| null) => void) \| undefined`               |         |                                                                                                                                                                                        |
| filteredKeys      | `string[] \| undefined`                                      |         | Controlled set of `series.key` values to hide from the plot.                                                                                                                           |
| onZoomChange      | `((range: LineChartZoomRange \| null) => void) \| undefined` |         | Fired after the user confirms a brush selection.                                                                                                                                       |
| syncId            | `string \| number \| undefined`                              |         | Charts that share a `syncId` synchronise their tooltip cursor.                                                                                                                         |
| syncMethod        | `complex`                                                    |         | How sibling `syncId` charts match X positions.                                                                                                                                         |
| defaultChecked    | `boolean \| undefined`                                       |         |                                                                                                                                                                                        |
| defaultValue      | `string \| number \| readonly string[] \| undefined`         |         |                                                                                                                                                                                        |
| autoFocus         | `boolean \| undefined`                                       |         |                                                                                                                                                                                        |
| id                | `string \| undefined`                                        |         |                                                                                                                                                                                        |
| tabIndex          | `number \| undefined`                                        |         |                                                                                                                                                                                        |
| title             | `string \| undefined`                                        |         |                                                                                                                                                                                        |
| rel               | `string \| undefined`                                        |         |                                                                                                                                                                                        |
| onChange          | `ChangeEventHandler<T, Element> \| undefined`                |         |                                                                                                                                                                                        |
| data-testid       | `string \| undefined`                                        |         |                                                                                                                                                                                        |

### BarListBar

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                           |
| -------------- | ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| color          | `ChartColor \| undefined`                            |         | Built-in palette fill. Each colour maps to the `--color-badge-{color}-light` design-system token (dark-mode aware). Pass a Tailwind `bg-*` utility via `className` to use any other colour — it wins over the palette class through `tailwind-merge`. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                       |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                       |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                       |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                       |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                       |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                       |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                       |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                       |

### BarListItem

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                    |
| -------------- | ---------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| value \*       | `number`                                             |         |                                                                                                                                                                                                                |
| selected       | `boolean \| undefined`                               | `false` | Marks the row as visually active (selected / filtered). Applies the hover background + `aria-current`. The bar width and percent label are driven purely by `value / max` — `selected` never changes the fill. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                |

### BarListLabel

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### BarListPercent

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                    |
| -------------- | ---------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| digits         | `number \| undefined`                                | `0`     | Number of fractional digits. Defaults to `0`.                                                                                                                                                                                                                                                  |
| variant        | `BarListPercentVariant \| undefined`                 | `split` | Color treatment for the value and the `%` symbol. - `split` (default, matches Figma) — value uses `text-text-primary`, symbol uses `text-text-secondary`. - `muted` — both tokens use `text-text-secondary`. - `inherit` — both tokens inherit the parent's color (e.g. match `BarListValue`). |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                                |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                                |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                                |

### BarList

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                    |
| -------------- | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| max \*         | `number`                                             |         | Value at which a bar reaches 100%. Required. - Percent inputs → `max={100}`. - Fractions → `max={1}`. - Raw counts → `Math.max(...values)` or the total. Invalid values (non-finite, zero, negative) render every row empty with a 0% label and log a single dev-only warning. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                |
| data-testid    | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                |

### BarListSkeleton

| Prop           | Type                                                 | Default | Description                                         |
| -------------- | ---------------------------------------------------- | ------- | --------------------------------------------------- |
| rows           | `number \| undefined`                                | `5`     | Number of skeleton rows to render. Defaults to `5`. |
| defaultChecked | `boolean \| undefined`                               |         |                                                     |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                     |
| autoFocus      | `boolean \| undefined`                               |         |                                                     |
| id             | `string \| undefined`                                |         |                                                     |
| tabIndex       | `number \| undefined`                                |         |                                                     |
| title          | `string \| undefined`                                |         |                                                     |
| rel            | `string \| undefined`                                |         |                                                     |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                     |
| data-testid    | `string \| undefined`                                |         |                                                     |

### BarListValue

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### ChartActions

| Prop           | Type                                                 | Default | Description                                                                                                               |
| -------------- | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------- |
| alwaysVisible  | `boolean \| undefined`                               | `false` | Keep actions visible regardless of card hover/focus. Defaults to `false` — the block fades in on card hover/focus-within. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                           |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                           |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                           |
| id             | `string \| undefined`                                |         |                                                                                                                           |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                           |
| title          | `string \| undefined`                                |         |                                                                                                                           |
| rel            | `string \| undefined`                                |         |                                                                                                                           |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                           |

### ChartEmpty

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### ChartHeader

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### Chart

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### ChartTitle

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### ColumnChartBody

| Prop           | Type                                                 | Default | Description                                                                                                                                                                         |
| -------------- | ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| height         | `number \| undefined`                                |         | Fixed plot height in pixels. Leave it unset to follow the card: the plot starts at the Figma 164px (card 220) and grows or shrinks with the `<Chart>` height, down to a 128px card. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                     |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                     |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                     |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                     |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                     |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                     |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                     |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                     |

### ColumnChart

| Prop           | Type                                                 | Default | Description                                                                                                                                                       |
| -------------- | ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data \*        | `T[]`                                                |         | One entry per column (step), sorted ascending by `xKey`.                                                                                                          |
| series \*      | `LineChartSeries<Extract<keyof T, string>>[]`        |         | The categories each column is split into, in legend order — the first one stacks on top. The same schema drives the legend, the parts and the hover popover rows. |
| xKey \*        | `Extract<keyof T, string>`                           |         | Key on each datum used as the X-axis value (the step: a day, an hour, …).                                                                                         |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                   |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                   |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                   |
| id             | `string \| undefined`                                |         |                                                                                                                                                                   |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                   |
| title          | `string \| undefined`                                |         |                                                                                                                                                                   |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                   |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                   |
| data-testid    | `string \| undefined`                                |         |                                                                                                                                                                   |

### ColumnChartXAxis

| Prop          | Type                                                                            | Default            | Description                                                                                                                                                                             |
| ------------- | ------------------------------------------------------------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tickFormatter | `((value: unknown, index: number) => string) \| undefined`                      |                    | Format the rendered tick label. Receives the raw `xKey` value of the column.                                                                                                            |
| interval      | `number \| "preserveStart" \| "preserveEnd" \| "preserveStartEnd" \| undefined` | `preserveStartEnd` | Recharts tick interval. Defaults to `'preserveStartEnd'`: the first and last columns keep their labels and middle ones drop out when the labels would collide. `0` labels every column. |
| minTickGap    | `number \| undefined`                                                           |                    | Minimum gap (in pixels) between rendered tick labels.                                                                                                                                   |

### HorizontalBarStack

| Prop               | Type                                                 | Default | Description                                                                                                                                                                                                                             |
| ------------------ | ---------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data \*            | `HorizontalBarStackDatum[]`                          |         | Segments + legend. One array drives both, so colors stay in sync.                                                                                                                                                                       |
| total              | `number \| undefined`                                |         | Bar denominator. `> sum(data.value)` → grey remainder tail. Default: `sum(data.value)`.                                                                                                                                                 |
| legend             | `boolean \| undefined`                               | `true`  | Show/hide the legend. Default: true.                                                                                                                                                                                                    |
| activeName         | `string \| null \| undefined`                        |         | Controlled hover target, joined by `name`. Omitted → managed internally. Set together with `onActiveNameChange` to sync hover across charts (e.g. a sibling highlights the same series). Mirrors `PieChart`.                            |
| onActiveNameChange | `((name: string \| null) => void) \| undefined`      |         |                                                                                                                                                                                                                                         |
| selectedNames      | `string[] \| undefined`                              |         | Names to emphasise. When non-empty, non-selected segments + legend items fade. Hover (`activeName`) wins — while a series is hovered, only it stays bright. Names not in `data` are ignored.                                            |
| onSelect           | `((name: string) => void) \| undefined`              |         | Click-to-filter. When provided, legend items become interactive (`role='button'`, `tabIndex=0`, Enter/Space) and fire with the clicked datum's `name`. The caller owns the filter (typically: drive `selectedNames`, or filter `data`). |
| title              | `string \| undefined`                                |         |                                                                                                                                                                                                                                         |
| defaultChecked     | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                         |
| defaultValue       | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                         |
| autoFocus          | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                         |
| id                 | `string \| undefined`                                |         |                                                                                                                                                                                                                                         |
| tabIndex           | `number \| undefined`                                |         |                                                                                                                                                                                                                                         |
| rel                | `string \| undefined`                                |         |                                                                                                                                                                                                                                         |
| onChange           | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                         |
| data-testid        | `string \| undefined`                                |         |                                                                                                                                                                                                                                         |

### HorizontalBarStackSkeleton

| Prop           | Type                                                 | Default | Description                                          |
| -------------- | ---------------------------------------------------- | ------- | ---------------------------------------------------- |
| legendItems    | `number \| undefined`                                | `3`     | Number of legend placeholder pills. Defaults to `3`. |
| defaultChecked | `boolean \| undefined`                               |         |                                                      |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                      |
| autoFocus      | `boolean \| undefined`                               |         |                                                      |
| id             | `string \| undefined`                                |         |                                                      |
| tabIndex       | `number \| undefined`                                |         |                                                      |
| title          | `string \| undefined`                                |         |                                                      |
| rel            | `string \| undefined`                                |         |                                                      |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                      |
| data-testid    | `string \| undefined`                                |         |                                                      |

### LineChartBody

| Prop           | Type                                                 | Default               | Description                                                                                                                                       |
| -------------- | ---------------------------------------------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| height         | `number \| undefined`                                | `DEFAULT_BODY_HEIGHT` | Body height passed to recharts' `<ResponsiveContainer>`. Defaults to the Figma single-line plot height (`LINE_CARD_HEIGHT - LINE_HEADER_HEIGHT`). |
| defaultChecked | `boolean \| undefined`                               |                       |                                                                                                                                                   |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |                       |                                                                                                                                                   |
| autoFocus      | `boolean \| undefined`                               |                       |                                                                                                                                                   |
| id             | `string \| undefined`                                |                       |                                                                                                                                                   |
| tabIndex       | `number \| undefined`                                |                       |                                                                                                                                                   |
| title          | `string \| undefined`                                |                       |                                                                                                                                                   |
| rel            | `string \| undefined`                                |                       |                                                                                                                                                   |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |                       |                                                                                                                                                   |

### LineChartEmpty

| Prop           | Type                                                 | Default               | Description                                                 |
| -------------- | ---------------------------------------------------- | --------------------- | ----------------------------------------------------------- |
| height         | `number \| undefined`                                | `DEFAULT_BODY_HEIGHT` | Body height override. Defaults to the standard plot height. |
| defaultChecked | `boolean \| undefined`                               |                       |                                                             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |                       |                                                             |
| autoFocus      | `boolean \| undefined`                               |                       |                                                             |
| id             | `string \| undefined`                                |                       |                                                             |
| tabIndex       | `number \| undefined`                                |                       |                                                             |
| title          | `string \| undefined`                                |                       |                                                             |
| rel            | `string \| undefined`                                |                       |                                                             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |                       |                                                             |
| data-testid    | `string \| undefined`                                |                       |                                                             |

### LineChartGrid

| Prop           | Type                   | Default | Description                                                                                                                                                                                                                                  |
| -------------- | ---------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| vertical       | `boolean \| undefined` | `false` | Render vertical grid lines in addition to the default horizontal ones.                                                                                                                                                                       |
| keepTopLine    | `boolean \| undefined` | `false` | Keep the topmost horizontal grid line unconditionally. By default the line is dropped only when it would visually crowd the chart's top edge — see \{@link dropEdgeGridLines} for the threshold (Figma "no top x-line" rule).                |
| keepBottomLine | `boolean \| undefined` | `false` | Keep the bottommost horizontal grid line. By default the line is dropped because the solid `<LineChartXAxis>` axis line owns the bottom rail — set to `true` when the X-axis line is hidden and the grid should draw the bottom rail itself. |

### LineChartHoverPopoverDot

| Prop           | Type                                                 | Default | Description                                                                        |
| -------------- | ---------------------------------------------------- | ------- | ---------------------------------------------------------------------------------- |
| color          | `(string & {}) \| ChartColor \| undefined`           |         | Palette token or CSS colour. Omitted → no inline fill (lets a `className` bg win). |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                    |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                    |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                    |
| id             | `string \| undefined`                                |         |                                                                                    |
| tabIndex       | `number \| undefined`                                |         |                                                                                    |
| title          | `string \| undefined`                                |         |                                                                                    |
| rel            | `string \| undefined`                                |         |                                                                                    |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                    |

### LineChartHoverPopover

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### LineChartHoverPopoverRow

| Prop           | Type                                                                         | Default | Description                                                                 |
| -------------- | ---------------------------------------------------------------------------- | ------- | --------------------------------------------------------------------------- |
| series \*      | `LineChartSeries<string>`                                                    |         | Series whose colour and label feed the row.                                 |
| value          | `string \| number \| null \| undefined`                                      |         | Raw datum value at the active index. `null`/`undefined` renders an em-dash. |
| formatValue    | `((value: string \| number \| null \| undefined) => ReactNode) \| undefined` |         | Optional value formatter. Defaults to the shared locale formatting.         |
| defaultChecked | `boolean \| undefined`                                                       |         |                                                                             |
| defaultValue   | `string \| number \| readonly string[] \| undefined`                         |         |                                                                             |
| autoFocus      | `boolean \| undefined`                                                       |         |                                                                             |
| id             | `string \| undefined`                                                        |         |                                                                             |
| tabIndex       | `number \| undefined`                                                        |         |                                                                             |
| title          | `string \| undefined`                                                        |         |                                                                             |
| rel            | `string \| undefined`                                                        |         |                                                                             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`                                |         |                                                                             |

### LineChartHoverPopoverTimestamp

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### LineChartLegendItem

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                  |
| -------------- | ---------------------------------------------------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| seriesKey \*   | `string`                                             |         | Joins to `LineChartSeries.key`. Drives hover sync, dim, and `aria-current`.                                                                                                                                                                                                                  |
| selected       | `boolean \| undefined`                               |         | Explicit selection state. When omitted, falls back to "not in `filteredKeys`". `true` = row is on (line drawn); `false` = row is off (line hidden, dimmed). Passing this prop fully overrides the context — useful when the legend renders rows that are not part of the chart's filter set. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                              |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                              |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                              |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                              |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                              |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                              |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                              |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                              |

### LineChartLegend

| Prop           | Type                                                 | Default      | Description                                                                                                                                                                                                                                                                                               |
| -------------- | ---------------------------------------------------- | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| orientation    | `LineChartLegendOrientation \| undefined`            | `horizontal` | How legend rows lay out inside the legend itself. Defaults to `'horizontal'`. Use `'vertical'` when the legend sits to the side of the chart (the consumer controls placement by JSX child order or by wrapping body+legend in an `<HStack>`). Layout-vs-orientation is the only knob the legend exposes. |
| align          | `"center" \| "end" \| "start" \| undefined`          | `start`      | Cross-axis alignment of the legend rows. Default `'start'`.                                                                                                                                                                                                                                               |
| defaultChecked | `boolean \| undefined`                               |              |                                                                                                                                                                                                                                                                                                           |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |              |                                                                                                                                                                                                                                                                                                           |
| autoFocus      | `boolean \| undefined`                               |              |                                                                                                                                                                                                                                                                                                           |
| id             | `string \| undefined`                                |              |                                                                                                                                                                                                                                                                                                           |
| tabIndex       | `number \| undefined`                                |              |                                                                                                                                                                                                                                                                                                           |
| title          | `string \| undefined`                                |              |                                                                                                                                                                                                                                                                                                           |
| rel            | `string \| undefined`                                |              |                                                                                                                                                                                                                                                                                                           |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |              |                                                                                                                                                                                                                                                                                                           |

### LineChartLine

| Prop             | Type                                                                     | Default             | Description                                                                    |
| ---------------- | ------------------------------------------------------------------------ | ------------------- | ------------------------------------------------------------------------------ |
| seriesKey \*     | `string`                                                                 |                     | Joins to `LineChartSeries.key` from the root `series` prop.                    |
| curve            | `"linear" \| "monotone" \| undefined`                                    | `monotone`          | Recharts curve type. Defaults to `'monotone'`.                                 |
| disableAnimation | `boolean \| undefined`                                                   | `false`             | Force-disable the recharts mount animation.                                    |
| connectNulls     | `boolean \| undefined`                                                   | `false`             | Recharts pass-through — when `true`, the line bridges `null`/`undefined` gaps. |
| strokeWidth      | `number \| undefined`                                                    | `LINE_STROKE_WIDTH` | Stroke width override. Defaults to `LINE_STROKE_WIDTH`.                        |
| onClick          | `((event: MouseEvent<SVGPathElement, MouseEvent>) => void) \| undefined` |                     |                                                                                |
| onMouseEnter     | `((event: MouseEvent<SVGPathElement, MouseEvent>) => void) \| undefined` |                     |                                                                                |
| onMouseLeave     | `((event: MouseEvent<SVGPathElement, MouseEvent>) => void) \| undefined` |                     |                                                                                |

### LineChart

| Prop              | Type                                                         | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
| ----------------- | ------------------------------------------------------------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data \*           | `T[]`                                                        |         | Long-form data array, one entry per X position.                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| series \*         | `LineChartSeries<Extract<keyof T, string>>[]`                |         | Schema describing each line drawn from `data`.                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
| xKey \*           | `Extract<keyof T, string>`                                   |         | Key on each datum used as the X-axis value. Required — a silent fallback would hide key-name typos until the chart renders empty.                                                                                                                                                                                                                                                                                                                                                                         |
| activeKey         | `string \| null \| undefined`                                |         | Controlled hover key — pass alongside `onActiveKeyChange` for cross-chart sync. **Heads-up:** if the controlled value points at a series key that no longer exists in `series` (filter, schema change, refresh), the chart pushes `null` back through `onActiveKeyChange` so sibling charts stop highlighting a stale key. If you wire `activeKey` to external state, the snap-to-null write will arrive as a normal state change — do not be surprised when your value resets after a series disappears. |
| onActiveKeyChange | `((key: string \| null) => void) \| undefined`               |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| filteredKeys      | `string[] \| undefined`                                      |         | Controlled set of `series.key` values to hide from the plot.                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| onZoomChange      | `((range: LineChartZoomRange \| null) => void) \| undefined` |         | Fired after the user confirms a brush selection.                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
| syncId            | `string \| number \| undefined`                              |         | Charts that share a `syncId` synchronise their tooltip cursor and brush via recharts' built-in middleware — hovering one chart highlights the matching X on every sibling chart with the same id. Pair with `activeKey` + `onActiveKeyChange` if you also want the _series_ highlight to sync.                                                                                                                                                                                                            |
| syncMethod        | `complex`                                                    |         | How sibling `syncId` charts match X positions. Defaults to `'index'` (Recharts' default). Use `'value'` when the synced charts have different dataset lengths but share categorical X values.                                                                                                                                                                                                                                                                                                             |
| defaultChecked    | `boolean \| undefined`                                       |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| defaultValue      | `string \| number \| readonly string[] \| undefined`         |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| autoFocus         | `boolean \| undefined`                                       |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| id                | `string \| undefined`                                        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| tabIndex          | `number \| undefined`                                        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| title             | `string \| undefined`                                        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| rel               | `string \| undefined`                                        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| onChange          | `ChangeEventHandler<T, Element> \| undefined`                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| data-testid       | `string \| undefined`                                        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |

### LineChartTooltip

| Prop           | Type                                           | Default | Description                                              |
| -------------- | ---------------------------------------------- | ------- | -------------------------------------------------------- |
| xTickFormatter | `((value: unknown) => ReactNode) \| undefined` |         | Custom formatter for the default popover timestamp slot. |

### LineChartXAxis

| Prop          | Type                                                                                                          | Default            | Description                                                                                                                                                                                                                                                                                                                   |
| ------------- | ------------------------------------------------------------------------------------------------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| tickFormatter | `((value: unknown, index: number) => string) \| undefined`                                                    |                    | Format the rendered tick label. Receives the raw datum value at the tick.                                                                                                                                                                                                                                                     |
| density       | `LineChartXAxisDensity \| undefined`                                                                          |                    | Curated tick-spacing preset (`'sparse' \| 'normal' \| 'dense'`). Sets `minTickGap` to 64/32/16px respectively. Explicit `minTickGap` overrides the preset — reach for that escape hatch when no preset fits.                                                                                                                  |
| interval      | `number \| "preserveStart" \| "preserveEnd" \| "preserveStartEnd" \| "equidistantPreserveStart" \| undefined` | `preserveStartEnd` | Recharts tick interval — `0` to render every tick, the literal strings to auto-pick.                                                                                                                                                                                                                                          |
| tickCount     | `number \| undefined`                                                                                         |                    | Recharts target tick count.                                                                                                                                                                                                                                                                                                   |
| ticks         | `readonly (string \| number)[] \| undefined`                                                                  |                    | Explicit tick values. Overrides recharts' generator.                                                                                                                                                                                                                                                                          |
| minTickGap    | `number \| undefined`                                                                                         |                    | Minimum gap (in pixels) between rendered tick labels. Overrides `density`.                                                                                                                                                                                                                                                    |
| domain        | `[string \| number, string \| number] \| undefined`                                                           |                    | Recharts domain override — `['auto', 'auto']` by default.                                                                                                                                                                                                                                                                     |
| padding       | `"gap" \| { left?: number \| undefined; right?: number \| undefined; } \| "no-gap" \| undefined`              |                    | Padding between the plot edge and the first/last tick.                                                                                                                                                                                                                                                                        |
| type          | `"number" \| "category" \| undefined`                                                                         |                    | Recharts axis scale type — `'category'` (default for line charts) or `'number'` for continuous X.                                                                                                                                                                                                                             |
| hideTicks     | `boolean \| undefined`                                                                                        | `false`            | Render the axis area as a spacer (preserves layout, hides the labels).                                                                                                                                                                                                                                                        |
| axisLine      | `boolean \| undefined`                                                                                        | `true`             | Render the solid bottom axis line. Defaults to `true` — the line owns the bottom rail of the plot (the `<LineChartGrid>` drops its bottom horizontal grid line to avoid stacking on top of it). Pass `false` for sparkline-style plots; in that case set `<LineChartGrid keepBottomLine />` if a bottom rail is still wanted. |

### LineChartYAxis

| Prop          | Type                                                                        | Default              | Description                                                                       |
| ------------- | --------------------------------------------------------------------------- | -------------------- | --------------------------------------------------------------------------------- |
| tickFormatter | `((value: unknown, index: number) => string) \| undefined`                  |                      | Format the rendered tick label.                                                   |
| tickCount     | `number \| undefined`                                                       |                      | Recharts target tick count.                                                       |
| ticks         | `readonly (string \| number)[] \| undefined`                                |                      | Explicit tick values. Overrides recharts' generator.                              |
| domain        | `[string \| number, string \| number] \| undefined`                         |                      | Recharts domain override.                                                         |
| padding       | `{ top?: number \| undefined; bottom?: number \| undefined; } \| undefined` |                      | Padding between the plot edge and the first/last tick.                            |
| width         | `number \| undefined`                                                       | `LINE_Y_LABEL_WIDTH` | Y-label gutter width. Defaults to the Figma-mandated `LINE_Y_LABEL_WIDTH` (38px). |
| hideTicks     | `boolean \| undefined`                                                      | `false`              | Render the axis area as a spacer (preserves layout, hides the labels).            |

### LineChartZoomBrush

| Prop         | Type                                                      | Default              | Description                                                                                                                                                                                                                                                                        |
| ------------ | --------------------------------------------------------- | -------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| disabled     | `boolean \| undefined`                                    | `false`              | When `true` the zoom interaction is removed entirely.                                                                                                                                                                                                                              |
| formatRange  | `((range: LineChartZoomRange) => ReactNode) \| undefined` | `defaultFormatRange` | Override the default range text rendered inside the popover.                                                                                                                                                                                                                       |
| confirmLabel | `ReactNode`                                               | `Zoom in`            | Override the default "Zoom in" label on the confirm button.                                                                                                                                                                                                                        |
| container    | `HTMLElement \| null \| undefined`                        |                      | Portal target for the floating range/confirm popover. Defaults to `document.body`. Pass a dialog/modal node to keep the popover inside the focus-trapped subtree — without this the portal escapes the focus context and tabbing from the confirm button lands outside the dialog. |

### LineChartZoomPopoverConfirm

| Prop           | Type                                                 | Default  | Description |
| -------------- | ---------------------------------------------------- | -------- | ----------- |
| disabled       | `boolean \| undefined`                               |          |             |
| name           | `string \| undefined`                                |          |             |
| type           | `"button" \| "submit" \| "reset" \| undefined`       | `button` |             |
| value          | `string \| number \| readonly string[] \| undefined` |          |             |
| defaultChecked | `boolean \| undefined`                               |          |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |          |             |
| autoFocus      | `boolean \| undefined`                               |          |             |
| id             | `string \| undefined`                                |          |             |
| tabIndex       | `number \| undefined`                                |          |             |
| title          | `string \| undefined`                                |          |             |
| rel            | `string \| undefined`                                |          |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |          |             |

### LineChartZoomPopover

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### LineChartZoomPopoverRange

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### MetricCaption

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### MetricDelta

| Prop      | Type                               | Default | Description                                                                                                                                                                                                                    |
| --------- | ---------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| value \*  | `number`                           |         | Magnitude shown in the chip; rendered as `Math.abs(value).toLocaleString('en-US')`.                                                                                                                                            |
| trend     | `ChartDeltaTrend \| undefined`     |         | Arrow direction. Defaults to the sign of `value` (`>= 0` → up).                                                                                                                                                                |
| sentiment | `ChartDeltaSentiment \| undefined` |         | Colour = meaning, and it is independent of the arrow: `positive` → green, `negative` → red, `neutral` → slate. Defaults to `neutral`. An increase can therefore read as negative (red ↑) and a decrease as positive (green ↓). |

### MetricHeader

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### Metric

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### MetricSkeleton

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |
| data-testid    | `string \| undefined`                                |         |             |

### MetricSparkline

| Prop           | Type                                                        | Default | Description                                                                                                                                             |
| -------------- | ----------------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| data \*        | `MetricSparklinePoint[]`                                    |         | The trend over the period, oldest first.                                                                                                                |
| color          | `MetricSparklineColor \| undefined`                         | `brand` | Line colour. Independent of the `MetricDelta` sentiment — set both. `brand` (default) · `positive` (success) · `negative` (danger) · `neutral` (slate). |
| label          | `ReactNode`                                                 |         | Series name on the hover popover row (Figma "Attribute").                                                                                               |
| formatX        | `((x: string \| number \| Date) => ReactNode) \| undefined` |         | Formats the hovered point's `x` for the popover. Defaults to `1 Jan, 2026` for dates.                                                                   |
| formatValue    | `((value: number) => ReactNode) \| undefined`               |         | Formats the hovered value. Defaults to `toLocaleString('en-US')`.                                                                                       |
| title          | `string \| undefined`                                       |         |                                                                                                                                                         |
| defaultChecked | `boolean \| undefined`                                      |         |                                                                                                                                                         |
| defaultValue   | `string \| number \| readonly string[] \| undefined`        |         |                                                                                                                                                         |
| autoFocus      | `boolean \| undefined`                                      |         |                                                                                                                                                         |
| id             | `string \| undefined`                                       |         |                                                                                                                                                         |
| tabIndex       | `number \| undefined`                                       |         |                                                                                                                                                         |
| rel            | `string \| undefined`                                       |         |                                                                                                                                                         |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`               |         |                                                                                                                                                         |
| data-testid    | `string \| undefined`                                       |         |                                                                                                                                                         |

### MetricTotal

| Prop           | Type                                                 | Default | Description                                                                            |
| -------------- | ---------------------------------------------------- | ------- | -------------------------------------------------------------------------------------- |
| connector      | `MetricTotalConnector \| undefined`                  | `slash` | How the denominator reads: `/120` (`slash`) · `of 120` (`of`) · `120 total` (`total`). |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                        |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                        |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                        |
| id             | `string \| undefined`                                |         |                                                                                        |
| tabIndex       | `number \| undefined`                                |         |                                                                                        |
| title          | `string \| undefined`                                |         |                                                                                        |
| rel            | `string \| undefined`                                |         |                                                                                        |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                        |

### MetricValue

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### LegendDot

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### PieChartCenterLabel

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                   |
| -------------- | ---------------------------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| hoverSync      | `boolean \| undefined`                               | `true`  | When `true` (default), the label tracks the hovered slice/legend row — so a `pluralize` rules object picks the form for the hovered datum's value rather than the chart total. Has no effect when `pluralize` is omitted.                                                     |
| pluralize      | `PieChartCenterLabelPluralRules \| undefined`        |         | Optional pluralization rules. When provided, the label content is selected from the rules using `Intl.PluralRules` for the currently visible count (the hovered datum's value when `hoverSync` is on, otherwise the chart total). When omitted, `children` renders unchanged. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                               |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                               |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                               |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                               |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                               |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                               |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                               |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                               |

### PieChartCenter

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### PieChartCenterValue

| Prop               | Type                                                 | Default                     | Description                                                                                                                                                                                                                                                                                   |
| ------------------ | ---------------------------------------------------- | --------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| hoverSync          | `boolean \| undefined`                               | `true`                      | When `true` (default), hovering a slice or legend row replaces `children` with the hovered datum's value (formatted via `formatHoveredValue`). Set to `false` to keep `children` visible regardless of hover state — useful when the centre value should always reflect the unfiltered total. |
| formatHoveredValue | `((datum: PieChartDatum) => ReactNode) \| undefined` | `defaultFormatHoveredValue` | Formatter applied to the hovered datum when `hoverSync` is enabled. Defaults to `datum.value.toLocaleString()`. Pass a custom formatter to keep the hover format aligned with whatever formatter produced `children` (e.g. compact notation, units).                                          |
| defaultChecked     | `boolean \| undefined`                               |                             |                                                                                                                                                                                                                                                                                               |
| defaultValue       | `string \| number \| readonly string[] \| undefined` |                             |                                                                                                                                                                                                                                                                                               |
| autoFocus          | `boolean \| undefined`                               |                             |                                                                                                                                                                                                                                                                                               |
| id                 | `string \| undefined`                                |                             |                                                                                                                                                                                                                                                                                               |
| tabIndex           | `number \| undefined`                                |                             |                                                                                                                                                                                                                                                                                               |
| title              | `string \| undefined`                                |                             |                                                                                                                                                                                                                                                                                               |
| rel                | `string \| undefined`                                |                             |                                                                                                                                                                                                                                                                                               |
| onChange           | `ChangeEventHandler<T, Element> \| undefined`        |                             |                                                                                                                                                                                                                                                                                               |

### PieChartDonut

| Prop             | Type                                                 | Default | Description                                                                                                                                         |
| ---------------- | ---------------------------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| inactiveOpacity  | `number \| undefined`                                | `0.3`   | Opacity applied to slices that are not currently hovered. Defaults to `0.3`. Set to `1` to disable the hover-dim effect.                            |
| disableAnimation | `boolean \| undefined`                               | `false` | Disable the recharts mount/transition animation. Defaults to `false`. Set `true` in test/screenshot environments where deterministic frames matter. |
| defaultChecked   | `boolean \| undefined`                               |         |                                                                                                                                                     |
| defaultValue     | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                     |
| autoFocus        | `boolean \| undefined`                               |         |                                                                                                                                                     |
| id               | `string \| undefined`                                |         |                                                                                                                                                     |
| tabIndex         | `number \| undefined`                                |         |                                                                                                                                                     |
| title            | `string \| undefined`                                |         |                                                                                                                                                     |
| rel              | `string \| undefined`                                |         |                                                                                                                                                     |
| onChange         | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                     |

### PieChartLegendItem

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------------- | ---------------------------------------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| name \*        | `string`                                             |         | Identifier matching a `PieChartDatum.name` from the root `data` prop. Drives both the percent calculation and the bidirectional hover sync with the donut slice.                                                                                                                                                                                                                                                                                                                                                                                                             |
| value          | `number \| undefined`                                |         | Optional override for the value used in the percent calculation. Defaults to looking the value up from the root `data` array by `name`. Pass an explicit value when the legend renders entries that are not part of the donut (e.g. a synthetic "Other" row).                                                                                                                                                                                                                                                                                                                |
| selected       | `boolean \| undefined`                               |         | Visually marks the row as the selected/filtered datum — applies `bg-states-primary-active` and `aria-current`. When omitted, the row falls back to membership in the root's `selectedNames` set (if provided). When passed explicitly (`true` or `false`) it fully overrides the context — useful when the legend renders rows that aren't part of the chart's multi-selection (e.g. a single filtered view). The resolved value also feeds the dim calculation: a row resolved to `selected=false` while _some_ peer is selected will fade like any other non-selected row. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |

### PieChartLegendPercent

| Prop           | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                                               |
| -------------- | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| digits         | `number \| undefined`                                | `0`     | Number of fractional digits in the percent label. Defaults to `0`.                                                                                                                                                                                                                                                        |
| variant        | `PieChartLegendPercentVariant \| undefined`          | `split` | Color treatment for the value and the `%` symbol. Mirrors `BarListPercent`. - `split` (default, matches Figma) — value uses `text-text-primary`, symbol uses `text-text-secondary`. - `muted` — both tokens use `text-text-secondary`. - `inherit` — both inherit the parent's color (e.g. follow `PieChartLegendValue`). |
| defaultChecked | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                           |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                                                           |
| autoFocus      | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                           |
| id             | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                           |
| tabIndex       | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                           |
| title          | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                           |
| rel            | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                           |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                                                           |

### PieChartLegend

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### PieChartLegendValue

| Prop           | Type                                                 | Default | Description |
| -------------- | ---------------------------------------------------- | ------- | ----------- |
| defaultChecked | `boolean \| undefined`                               |         |             |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |             |
| autoFocus      | `boolean \| undefined`                               |         |             |
| id             | `string \| undefined`                                |         |             |
| tabIndex       | `number \| undefined`                                |         |             |
| title          | `string \| undefined`                                |         |             |
| rel            | `string \| undefined`                                |         |             |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |             |

### PieChart

| Prop               | Type                                                 | Default | Description                                                                                                                                                                                                                                                                                                                                                                                                                          |
| ------------------ | ---------------------------------------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| data \*            | `PieChartDatum[]`                                    |         | Each datum's `name` is the join key used by `PieChartLegendItem` to sync hover/active state. Non-finite or negative `value`s are coerced to 0 so recharts can draw them.                                                                                                                                                                                                                                                             |
| total              | `number \| undefined`                                |         | Override for the value used to compute percentages and the centre total. Defaults to `sum(data.value)`. Pass an explicit value when the centre label should reflect a different denominator — e.g. the unfiltered total while the chart shows a filtered view.                                                                                                                                                                       |
| activeName         | `string \| null \| undefined`                        |         | Controlled active slice. When provided, the component does not manage hover state internally — the parent must update it via `onActiveNameChange`.                                                                                                                                                                                                                                                                                   |
| onActiveNameChange | `((name: string \| null) => void) \| undefined`      |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| selectedNames      | `string[] \| undefined`                              |         | Multi-selection set. When non-empty, donut slices and legend rows whose `name` is not in the set fade so emphasis lands on the chosen group. Hover (`activeName`) wins — while the user points at a specific slice, only that one stays bright. Names not present in `data` are ignored. Pass a stable reference (`useMemo`/state) — an inline array literal recreates on every parent render and invalidates the internal Set memo. |
| defaultChecked     | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| defaultValue       | `string \| number \| readonly string[] \| undefined` |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| autoFocus          | `boolean \| undefined`                               |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| id                 | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| tabIndex           | `number \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| title              | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| rel                | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| onChange           | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| data-testid        | `string \| undefined`                                |         |                                                                                                                                                                                                                                                                                                                                                                                                                                      |

### PieChartSkeleton

| Prop           | Type                                                 | Default | Description                                                    |
| -------------- | ---------------------------------------------------- | ------- | -------------------------------------------------------------- |
| rows           | `number \| undefined`                                | `5`     | Number of skeleton rows in the legend column. Defaults to `5`. |
| defaultChecked | `boolean \| undefined`                               |         |                                                                |
| defaultValue   | `string \| number \| readonly string[] \| undefined` |         |                                                                |
| autoFocus      | `boolean \| undefined`                               |         |                                                                |
| id             | `string \| undefined`                                |         |                                                                |
| tabIndex       | `number \| undefined`                                |         |                                                                |
| title          | `string \| undefined`                                |         |                                                                |
| rel            | `string \| undefined`                                |         |                                                                |
| onChange       | `ChangeEventHandler<T, Element> \| undefined`        |         |                                                                |
| data-testid    | `string \| undefined`                                |         |                                                                |

## Explorer

