Skip to content
HooksPro

useChartInteraction

Pointer and keyboard behaviour of a chart: the active point, arrow keys, range selection and the live announcement.

The behaviour the WunderUI cartesian charts share, for a chart you draw yourself. Pointer movement sets the active point and leaving clears it; the arrow keys (up and down on horizontal charts), Home and End walk the points and announce each one; Escape clears point and range. With , dragging across the plot or Shift with the arrow keys selects a range. Spread on the focusable plot element and render in a polite live region.

See alsoLine ChartCandlestick Chart

Import

tsx
import { useChartInteraction } from "@wunderui/react/charts"

Comes with WunderUI Core and Pro, in the entry of the package from your plan. See the plans.

Signature

ts
useChartInteraction(o: ChartInteractionOptions): { active: number | null; range: ChartRange | null; announcement: string; handlers: { onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void; onPointerMove: (e: React.PointerEvent<HTMLDivElement>) => void; onPointerDown: (e: React.Poin…

Parameters

ParameterType
oChartInteractionOptions

Returns

FieldType
activenumber | null
rangeChartRange | null
announcementstring
handlers{ onKeyDown: (e: React.KeyboardEvent<HTMLDivElement>) => void; onPointerMove: (e: React.PointerEvent<HTMLDivElement>) => void; onPointerDown: (e: React.PointerEvent<HTMLDivElement>) => void; onPointerUp: (e: React.PointerEvent<HTMLDivEleme…

Examples

A focusable custom plot

tsx
import { useChartInteraction } from "@wunderui/react/charts"

export function Dots({ values, width }: { values: number[]; width: number }) {
  const step = width / values.length
  const ui = useChartInteraction({
    count: values.length,
    invert: (px) => Math.max(0, Math.min(values.length - 1, Math.floor(px / step))),
    describe: (i) => `Day ${i + 1}: ${values[i]}`,
  })
  return (
    <div tabIndex={0} role="group" aria-label="Daily values" className="rounded-md outline-none focus-visible:ring-2 focus-visible:ring-ring" {...ui.handlers}>
      <svg width={width} height={80} aria-hidden="true">
        {values.map((v, i) => (
          <circle key={i} cx={i * step + step / 2} cy={70 - v} r={ui.active === i ? 6 : 4} fill="var(--chart-1)" />
        ))}
      </svg>
      <p aria-live="polite" className="sr-only">{ui.announcement}</p>
    </div>
  )
}

Range selection

tsx
const ui = useChartInteraction({
  count: data.length,
  rangeSelectable: true,
  onSelectedRangeChange: (range) => setRange(range),
  invert,
  describe,
  describeRange: ([a, b]) => `${data[a].month} to ${data[b].month}`,
})

Notes

  • The active point and the range can be controlled (, ) or left to the hook (, ).
  • maps a pointer position inside the plot to a category index; radial charts pass for a 2-D hit test instead.
  • writes the sentence the live region reads for a point, for example "March: $84,250".
  • Give the plot element , a role and a label, and a visible focus ring.