# Chart kit

> A React chart toolkit: the palette, formatters, measuring container, axes, crosshair, tooltip, legend and data table charts share.

- Type: React helper (Hooks & Utilities)
- Access: Pro (the source needs a Wingo UI Pro plan, see https://wingo-ui.com/pricing)
- Version: 1.0.2
- Install: `npx wingo-ui@latest add chart-kit`
- Docs: https://wingo-ui.com/components/chart-kit

## Interaction

The demo is a small line chart assembled from the kit. Move the mouse over it for a crosshair and a tooltip that flips near the right edge. On a phone, tap a month to pin the readout above your finger, drag sideways to scrub (vertical drags still scroll the page), tap the same month again or anywhere outside to clear it. With the keyboard, Tab to the chart, then Left / Right walk the months, Home / End jump to the ends, PageUp / PageDown move by ten, Escape clears; a live region reads each point. Click or tap a legend entry to hide or show its series, hover or focus one to highlight it.

## Installation

```bash
npx wingo-ui@latest add chart-kit
```

Pro item: run `npx wingo-ui@latest login` once with a Pro account. The CLI adds the files, their dependencies and a version record for updates.

With shadcn: `npx shadcn@latest add @wingo-ui/chart-kit` (needs the @wingo-ui registry with your API key in components.json)

Files:

- `lib/chart-kit.tsx`

npm dependencies: `npm i motion d3-scale d3-shape && npm i -D @types/d3-scale @types/d3-shape`

Wingo UI dependencies (installed automatically):

- [useControllableState](https://wingo-ui.com/components/use-controllable-state) ([Markdown](https://wingo-ui.com/components/use-controllable-state.md))
- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Number format](https://wingo-ui.com/components/number-format) ([Markdown](https://wingo-ui.com/components/number-format.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))

## Usage

```tsx
import {
  ChartContainer,
  ChartSvg,
  ChartTooltip,
  ChartInspectLayer,
  chartLayout,
  niceScale,
  valueDomain,
  useChartInspect,
  formatChartValue,
} from "@/lib/chart-kit"

const data = [
  { month: "Jul", revenue: 106300 },
  { month: "Aug", revenue: 97500 },
  { month: "Sep", revenue: 128450 },
]

function Bars({ width, height }: { width: number; height: number }) {
  const layout = chartLayout({ width, height, showYAxis: false })
  const { scale: y } = niceScale(valueDomain(data.map((d) => d.revenue)), [layout.bottom, layout.top])
  const step = layout.innerWidth / data.length
  const positions = data.map((_, i) => layout.left + step * (i + 0.5))
  const inspect = useChartInspect({ positions })
  const i = inspect.activeIndex
  return (
    <>
      <ChartSvg width={width} height={height}>
        {data.map((d, index) => (
          <rect key={d.month} x={positions[index] - 12} width={24} y={y(d.revenue)} height={y(0) - y(d.revenue)} rx={4} fill="var(--series-1)" />
        ))}
      </ChartSvg>
      <ChartInspectLayer controller={inspect} label="Revenue by month" />
      <ChartTooltip
        x={i == null ? null : positions[i]}
        title={i == null ? "" : data[i].month}
        items={i == null ? [] : [{ key: "v", label: "Revenue", value: formatChartValue(data[i].revenue, { format: "currency", locale: "en-US", currency: "USD" }), color: "var(--series-1)", shape: "rect" }]}
      />
    </>
  )
}

export function RevenueBars() {
  return (
    <ChartContainer aria-label="Revenue by month" height={200}>
      {(size) => <Bars {...size} />}
    </ChartContainer>
  )
}
```

## API

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `valueFormat?` | `"number" \| "compact" \| "currency" \| "percent"` | `"currency"` | ChartFormatOptions.format in the demo: how values print in the tooltip, the ticks and the table. |
| `locale?` | `string` | `"en-US"` | The demo's locale for numbers and dates. Charts resolve theirs with useLocale. |
| `curve?` | `"monotone" \| "linear" \| "natural" \| "step"` | `"monotone"` | ChartCurve passed to getCurve for the lines and areas. |
| `tooltipMode?` | `"auto" \| "float" \| "fixed"` | `"auto"` | ChartTooltip mode: float beside the crosshair, fixed above the plot (the touch default), auto picks by pointer. |
| `height?` | `number` | `240` | ChartContainer height in px (reserved before measuring, so nothing shifts). |
| `showGrid?` | `boolean` | `true` | Draws ChartGrid hairlines at the value ticks. |
| `animated?` | `boolean` | `true` | ChartContainer animated: marks draw in when the chart scrolls into view. |
| `loading?` | `boolean` | `false` | ChartContainer loading: a skeleton in the plot's shape (loadingShape bars \| line \| donut \| gauge \| grid). |
| `empty?` | `boolean` | `false` | The demo passes no data: ChartContainer empty shows ChartEmpty with labels.empty. |
| `ChartContainer?` | `{ height?: number \| string = 240; surface?: string = "var(--surface)"; animated?: boolean = true; loading?; loadingShape?; empty?; emptyState?; labels?: Partial<ChartLabels>; table?; header?; footer?; children: (size: { width; height }) => ReactNode } & div props` |  | The figure (role figure, aria-label from props): sets the palette vars and --chart-surface, measures its width, reserves the height before measuring, renders loading / empty in the same box, and always renders the table (so it is in the server html). useChart() inside gives { width, height, reduced, touch, revealed, animated }. |

## Parts

### useChart (hook)

Reads the chart context inside ChartContainer: { width, height, reduced, touch, revealed, animated }. Throws outside a container.

### CHART_PALETTE (constant)

The Tailwind arbitrary classes that set --series-1..8 and --series-other, with separate light and dark steps checked for color blindness.

### SERIES_COLORS (constant)

The eight categorical slots as css vars, var(--series-1) to var(--series-8), in their fixed order.

### OTHER_COLOR (constant)

var(--series-other), the gray used past the eighth series instead of a cycled hue.

### TONE_CHART_COLORS (constant)

Tone name to chart color: neutral is the foreground ink, the rest map to the brand and status tokens.

### resolveChartColor (function)

Turns "series-3", a tone, "other" or any css color into a fill; without one, the slot for the series' position.

### seriesColor (function)

The palette slot for a 0-based series index, or OTHER_COLOR past the eighth.

### tint (function)

A transparent mix of a chart color at a percent, for area fills, heat cells and tracks.

### formatChartValue (function)

Formats one value for the tooltip and table as number, compact, currency (USD by default) or percent; null prints a dash.

### formatChartTick (function)

A short axis tick label: compact past 10,000 ("$128K", "1.3M"), whole percents.

### formatChartLabel (function)

Formats an x value for the axis, tooltip or table; ISO days and months become localized dates.

### parseChartDate (function)

Parses "2026-09-24" or "2026-09" as a local calendar date (not UTC), or returns null.

### inferSeries (function)

Lists the numeric keys of the first rows, minus the x key, as series when none are given.

### toNumber (function)

Returns a finite number as is and anything else as null, for reading data cells safely.

### useChartSeries (hook)

Resolves series with colors fixed by position, hidden state (controlled or not, the last one stays visible) and the highlighted series. Returns { all, visible, hidden, toggle, highlighted, setHighlighted }.

### CHART_CURVES (constant)

The d3 curve factory for each ChartCurve: linear, monotone, natural and step.

### getCurve (function)

The d3 curve for a ChartCurve name, monotone when undefined.

### stackData (function)

A d3 stack over rows with offset none, expand (100% shares) or diverging (negatives below zero).

### valueDomain (function)

The [min, max] of the values, widened to include zero when asked (bars and areas) and never empty.

### niceScale (function)

A nice linear scale and its ticks, about one tick per 56px of range.

### barPath (function)

The svg path of a bar with a rounded data end and a square base, vertical or horizontal.

### barPathReversed (function)

barPath flipped, for negative bars: the rounded end sits at the bottom or on the left.

### estimateTextWidth (function)

A deterministic width estimate for 11px tabular labels, so server and client reserve the same axis space.

### thinLabels (function)

Which of n evenly spaced labels fit without colliding, counted back from the newest so the last one always shows.

### useElementSize (hook)

A ref and the element's layout size from a ResizeObserver, 0 x 0 until mounted.

### X_AXIS_HEIGHT (constant)

The 24px reserved under the plot for the x axis labels.

### chartLayout (function)

The plot rectangle inside the chart, with room for the measured y labels and the x axis.

### DEFAULT_CHART_LABELS (constant)

The English default strings: empty, loading, table caption, total, other, the inspect hint and legend toggles.

### ChartSvg (component)

The aria-hidden svg drawing surface, sized to the container.

### ChartGrid (component)

Hairline grid lines at the value ticks, horizontal or vertical, in a faint foreground tint.

### ChartBaseline (component)

A stronger line at one value, usually zero.

### ChartReferenceLine (component)

A dashed target or average line across the plot with an optional label.

### ChartYAxis (component)

The value tick labels, 11px tabular and muted, on the start or end side.

### ChartXAxis (component)

The x labels, thinned from the newest backwards so they never collide.

### ChartCrosshair (component)

The vertical line that snaps to the inspected point.

### ChartDot (component)

A data point ringed in the surface color that grows when active.

### ChartGradient (component)

A linear gradient definition that fades a series color for area fills.

### nearestIndex (function)

The index whose position is closest to x, by binary search over ascending positions.

### useChartInspect (hook)

One inspector for hover, tap and scrub, and arrow keys. Returns { activeIndex, setActiveIndex, source, layerId, handlers }.

### ChartInspectLayer (component)

The focusable layer over the plot that receives pointer, touch and keys, with a live region for the keyboard readout.

### ChartTooltip (component)

The readout of the inspected point: floats beside the crosshair or pins above the plot on touch, flipping near the edge.

### ChartTooltipContent (component)

The tooltip's title, keyed rows and footer without the positioning, for custom popovers.

### ChartKey (component)

The small swatch of a series: a line, dashed line, square or dot.

### ChartLegend (component)

Keys for two or more series with optional values, toggle buttons (aria-pressed) and hover or focus highlight.

### ChartDataTable (component)

The table of numbers every chart ships, screen reader only unless visible is set.

### ChartLoading (component)

A skeleton in the chart's shape (bars, line, donut, gauge or grid) with an accessible label.

### ChartEmpty (component)

The empty state shown in the plot's box, with an optional icon and message.

### markTransition (function)

A spring transition for bars and segments with a capped stagger per index.

### DRAW_TRANSITION (constant)

The ease-out tween that draws lines in through pathLength.

### ChartSeries (type)

{ key, label?, color?, name? }: one series a chart reads from the data.

### ChartFormatOptions (type)

{ format?, currency?, decimals?, locale? } for the value and tick formatters.

### ChartLayout (type)

The plot rectangle: left, right, top, bottom, innerWidth, innerHeight and yAxisWidth.

### ChartLabels (type)

The strings a chart can override: empty, loading, table, total, other, inspectHint and the legend toggles.

### ChartTooltipItem (type)

One tooltip row: { key, label, value, color?, shape?, muted? }.

### ChartLegendItem (type)

One legend entry: { key, label, color, value?, hidden?, shape?, name? }.

### ChartContainerProps (type)

Props of ChartContainer: height, surface, animated, loading, empty, labels, table, header, footer and a render function.

## Examples

- **Series palette**: The eight categorical slots and their names.
- **Formatters**: Money, compact ticks, percents and dates in en-US.
- **Visible data table**: ChartDataTable as a real table under the chart.
- **Loading and empty**: The plot keeps its height in every state.
- **Pinned touch tooltip**: tooltipMode fixed, the default on coarse pointers.

## See also

- [Number format](https://wingo-ui.com/components/number-format) ([Markdown](https://wingo-ui.com/components/number-format.md))
- [Motion presets](https://wingo-ui.com/components/motion) ([Markdown](https://wingo-ui.com/components/motion.md))
- [Tones](https://wingo-ui.com/components/tones) ([Markdown](https://wingo-ui.com/components/tones.md))
- [useMediaQuery](https://wingo-ui.com/components/use-media-query) ([Markdown](https://wingo-ui.com/components/use-media-query.md))

---

Canonical: https://wingo-ui.com/components/chart-kit
More components: https://wingo-ui.com/components · Index for agents: https://wingo-ui.com/llms.txt
