Acronis UIKit
Components

ScatterChart

A typed scatter / bubble chart for correlation across two or three numeric fields.

Usage

import { ScatterChart } from '@acronis-platform/ui-react';
import type { ChartConfig } from '@acronis-platform/ui-react';

ScatterChart is a typed composition over the shared Chart primitives. Give it a series list (each { key, data } with its own points), a per-series config, and the numeric axis fields (xKey / yKey) — it renders a themed recharts scatter chart (tooltip, legend, axes, grid included), so you don't hand-compose recharts children. Add a zKey to size points by a third field (a bubble chart).

Each series carries its own point array (points aren't columns of a shared row the way bar/line/area series are), so the API takes a series list rather than dataKeys.

Series colors come from the palette prop, not from config — see Palettes. Each config entry, keyed by a series[].key, maps that series to a label and an optional tone that re-points it within the palette. ScatterChart resolves them into the --color-<key> custom properties its points fill from.

Examples

Two groups plotted on shared x/y axes, with a themed tooltip and legend:

const series = [
  { key: 'classA', data: [{ hours: 2, score: 55 }, { hours: 6, score: 78 }] },
  { key: 'classB', data: [{ hours: 1, score: 70 }, { hours: 9, score: 95 }] },
];

const config = {
  classA: { label: 'Class A' },
  classB: { label: 'Class B' },
} satisfies ChartConfig;

<ScatterChart
  config={config}
  series={series}
  xKey="hours"
  yKey="score"
  className="h-[360px] w-[520px]"
/>;

Turn it into a bubble chart by mapping a third numeric field to point size with zKey:

<ScatterChart config={config} series={series} xKey="hours" yKey="score" zKey="weight" zRange={[60, 500]} />

Change the marker with shape, and toggle the chrome with showGrid / showTooltip / showLegend:

<ScatterChart config={config} series={series} xKey="hours" yKey="score" shape="triangle" showLegend={false} />

Add axis titles and unit suffixes with xAxisLabel / yAxisLabel / xUnit / yUnit — both axes are numeric here, so both units apply. The titles inherit the theme token:

<ScatterChart
  config={config}
  series={series}
  xKey="hours"
  yKey="score"
  xAxisLabel="Hours studied"
  yAxisLabel="Score"
  yUnit="%"
/>

Custom tooltip

Replace the tooltip with a configured ChartTooltipContent — imported from the same library, so you never compose recharts yourself. Its formatter renders each row and labelFormatter the header, giving you custom formatting, per-series content, and extra fields:

import { ScatterChart, ChartTooltipContent } from '@acronis-platform/ui-react';

<ScatterChart
  config={config}
  series={series}
  xKey="hours"
  yKey="score"
  tooltipContent={
    <ChartTooltipContent
      hideLabel
      formatter={(value, name) => `${name}: ${value.toLocaleString()}`}
    />
  }
/>;

Format the tick values with xTickFormatter / yTickFormatter, or hide an axis with showXAxis / showYAxis — the shared axis knobs described under Formatting and hiding axes. A formatter can map numbers to labels, which the unit suffix can't:

import { ScatterChart } from '@acronis-platform/ui-react';

<ScatterChart
  config={config}
  series={series}
  xKey="hours"
  yKey="score"
  yTickFormatter={(score) =>
    Number(score) >= 80 ? 'High' : Number(score) >= 60 ? 'Mid' : 'Low'
  }
/>;

Animation

Charts render statically by default. Opt in to an entrance animation with animate, and tune it with animationDuration / animationBegin / animationEasing:

<ScatterChart config={config} data={data} animate animationDuration={800} animationEasing="ease-out" />

animate honors prefers-reduced-motion: for a visitor who has asked their system to reduce motion, the series render at their final geometry with no animation (the same applies when rendering on the server).

Accessibility

Neither ScatterChart nor the shared ChartContainer adds a role or an aria-* attribute of its own. What semantics the chart has come from recharts, whose accessibility layer is on by default and is not switched off here: the plot's <svg> renders role="application" with tabindex="0", so Tab reaches it and focusing it opens the tooltip on the first point. The left/right arrow keys step it from point to point. Enter toggles the tooltip rather than pinning it, and since focus has already opened one, the first Enter closes it — press Enter again, or an arrow key, to bring it back.

That surface has no accessible name, though, and the layer to fix that is this one rather than recharts. recharts takes title, desc and role as first-class chart props and writes them straight into the plot's <svg>; ScatterChart passes none of them down, because it spreads the props it doesn't consume onto its own root <div> and hands the recharts chart only the data and margins it computes itself. The <title> and <desc> recharts always emits therefore stay empty and a screen reader announces an unnamed application region. The tooltip is not a live region either: ChartTooltipContent renders plain markup with no role="status" or aria-live, so the coordinates it reveals as you arrow along are shown but never announced.

So name the chart from the outside: role and aria-label (or aria-labelledby) land on that same root <div>. Choose the role before you copy the snippet, though. role="img" names the chart and also makes its subtree presentational, hiding the plot from assistive technology while it stays in the tab order; that is the right trade when the picture is the whole message. Where the keyboard tooltip should stay reachable, wrap the chart in a <figure> with a <figcaption>, or pass role="group" with the same aria-label, and leave the plot's own semantics alone.

<ScatterChart
  role="img"
  aria-label="Exam score against hours studied, by class"
  config={config}
  series={series}
  xKey="hours"
  yKey="score"
/>

A name is not a text alternative. A scatter exists to show a relationship — the correlation, the cluster, the outlier — and that reading is nowhere in the label, so state it: a caption with the takeaway, a summary sentence, or the points in an adjacent Table. Note that shape sets the marker for every point rather than per series, so on a grouped scatter hue is the only thing separating one series from another; when that grouping is part of the finding, make sure it survives into the text alternative. The same goes for a bubble chart: zKey maps a third field to point area, which nothing announces.

Direction (RTL)

Under dir="rtl" the chrome around the plot mirrors on its own — the legend, the tooltip, and any readouts you compose alongside the chart are ordinary flow layout built from logical CSS utilities. The plot area itself deliberately stays left-to-right: recharts lays every mark out in physical SVG coordinates, so a mirrored x-axis would flip the reading order of the data without flipping the geometry that encodes it — and on a scatter that geometry is the finding, since the slope of a cloud of points would reverse with it. This is what mainstream charting libraries do by default.

ChartContainer pins .recharts-surface to direction: ltr so that holds whatever the page inherits, and the pin is load-bearing rather than a formality: recharts anchors axis tick text with the direction-relative SVG keywords text-anchor: start / end while placing each mark at a coordinate it computed in physical space, so an inherited dir="rtl" mirrors the text away from the geometry — end-anchored Y-axis ticks land inside the plot area, and rotated X-axis ticks drift. Text anchored middle is direction-immune either way: unrotated X-axis ticks and axis titles. Because the pin stops at the surface, the tooltip and the legend — HTML outside it — still mirror. Chart carries the measured detail.

API Reference

Prop

Type

Edit on GitHub

On this page