Theme studio

Design a theme, preview it live, then export it. Saved in this browser.

Quick picks #10b981
Generated scale
50100200300400500600700800900
Some text is below AA

ScatterChart

  • Stable
  • WCAG 2.2 evidence
  • RTL

A scatter (bubble) chart: points on two numeric axes, optionally sized by a third measure, split into series and into quadrants. Data driven: series in, SVG out; the same props render the static SVG on the server and the plot is laid out for the width of its container. Very large sets are thinned for drawing, never for the table. Accessibility: the figure is named by title and described by summary; the data table lists EVERY point with its series, x, y, size and quadrant (WCAG 1.1.1, 1.3.1). Points differ by colour AND marker glyph per series and the legend shows both (1.4.1); a point with a name has it written beside it, and the quadrant is text, not only a line. The plot is ONE tab stop with a roving focus. The arrow keys move to the nearest point in that direction on screen: only points beyond the current one in that direction count, the ones straight ahead are preferred to nearer ones off to the side, and every press makes progress, so there is no trap and no loop (2.1.1, 2.1.2). Points hidden behind another in a dense cluster are reached with Page Down and Page Up, which walk every point in reading order (left to right, top to bottom), and Home and End jump to the first and last. Hovering or focusing a point shows a tooltip with its values; it stays while hovered and closes with Escape (1.4.13). Bubbles have a stroke as well as a light fill. The draw-in is behind motion-safe:; the plot stays left-to-right in right-to-left pages while the card mirrors, and digits follow the locale. Axis ticks thin out at narrow widths (1.4.10). Consumer duties: a title that asks the question, a summary with the main message, units and titles on both axes, saying what the bubble size and the quadrants mean.

import { ScatterChart } from "@nexera-ui/react";
Loading example…
10
examples
29
props
4
live controls
1
platform
10
WCAG criteria
0
blocks use it

Try every prop. Copy the code.

Change the props and the code updates. Check light and dark, LTR and RTL, and phone width.

Loading…
pointLabels
title
description
isLegendHidden
Generated code
import { ScatterChart } from "@nexera-ui/react";

<ScatterChart />

Examples 9

The same examples as Storybook, rendered live. Open Code to copy one.

With legend

Each department in its own series shows in the legend with its own marker glyph (circle, square, diamond, triangle) as well as its colour, and can be hidden from it.

Loading example…

Series

A plain scatter in three series (no bubble sizes, no quadrants): each series has its own colour and marker glyph, shown in the legend.

Loading example…

Loading

Loading example…

Empty

Loading example…

Error state

Loading example…

Single point

One point: it sits in the middle of the plot with axes that hold it.

Loading example…

Many points

3,000 points: a deterministic sample of at most 1,000 is drawn (every occupied region of every series keeps a point, so the outlier survives), a note says so, and the table lists all 3,000. The arrow keys still move to the nearest drawn point.

Loading example…

Long labels

Long axis titles, series names and point names: the legend and the header wrap, names that do not fit are left out beside the bubbles, the table has them all.

Loading example…

Right to left

Right-to-left page: the card, legend and table mirror, the plot keeps its left-to-right axes (Right still means right on the screen), digits follow the locale.

Loading example…

Props 29

Press "Try it" on a card to load that prop into the playground.

29 props shown

series*Nexera
readonly ScatterSeries[]

The points, in one or more series. A series draws in its own colour and marker glyph; Figma's engagement chart has one series per department with one labelled bubble each. valueFormat, formatValue and formatAxisValue are not props of this chart: each axis has its own (xAxis, yAxis), because the two measures have different units.

Default –
xAxisNexera
ScatterAxis

The x axis: title, edges, ticks and number format.

Default –
yAxisNexera
ScatterAxis

The y axis: title, edges, ticks and number format.

Default –
sizeLabelNexera
string

Name of what the bubble size stands for ("Headcount"): the tooltip row, the point label and the table column. Translate it.

Default `labels.size`
sizeValueFormatNexera
NumberFormatOptions

Intl.NumberFormat options for the bubble sizes.

Default –
formatSizeNexera
(value: number) => string

Formats a bubble size for the tooltip, the point label and the table. Wins over sizeValueFormat.

Default –
quadrantsNexera
ScatterQuadrants

Dividing lines and quadrant names.

Default –
pointLabelsNexera
"auto" | "all" | "none"

Whether to write the name of each labelled point beside its bubble: auto does it for up to 40 drawn points, all tries for every labelled point, none never. A name that does not fit without touching another name or leaving the plot is left out; the tooltip, the point label and the table always have it.

Default auto
maxPointsNexera
number

The most points drawn (and focusable). With more, a deterministic sample is drawn that keeps the coverage of the data (every occupied region of every series keeps a point, so outliers survive) and a note under the plot says how many are shown. The data table always lists EVERY point, so nothing is hidden from assistive technology or from anyone who wants the numbers.

Default 1000
samplingNoteNexera
string

The note under the plot when points are left out. {shown} and {total} are replaced by the formatted counts. Translate it.

Default Showing {shown} of {total} points. The table lists all of them.
maxBubbleRadiusNexera
number

Radius in px of the largest bubble. The others follow the square root of their size.

Default 22
pointRadiusNexera
number

Radius in px of a point without a size.

Default 5
labelsNexera
Partial<ScatterLabels>

Texts the chart invents: table headers and tooltip rows. Translate them.

Default –
title*Nexera
string

Chart title: the question the chart answers ("Headcount"). Required: it names the figure, the plot and the data table (WCAG 1.1.1).

Default –
descriptionNexera
ReactNode

Secondary line under the title.

Default –
summary*Nexera
string

One or two sentences with what the chart shows and its main message ("Headcount grew from 96 to 128 over twelve months"). Required: it describes the figure for assistive technology (WCAG 1.1.1); the data table has the details.

Default –
rangeNexera
ChartRangeProps

Range switch in the header: 3M, 6M, 12M. Pass the data of the chosen range back in.

Default –
actionsNexera
ReactNode

Extra controls in the header, after the range switch.

Default –
kpiNexera
ChartKpiProps

KPI row above the plot: the headline number with an optional label or change badge.

Default –
stateNexera
ChartPlotState

The state that replaces the plot: loading (skeleton), empty or error. A chart without a value to plot shows the empty state by itself; pass { status: "empty", title, description, action } to give it your wording.

Default –
tableNexera
ChartTableOptions

The data table that is the text alternative: caption, first-column header and whether it is visible or only for assistive technology.

Default –
localeNexera
string

Locale of digits and separators.

Default the `NexeraProvider` locale
heightNexera
number

Height of the plot in px. The card grows with the header, KPI and legend around it.

Default 296
isLegendHiddenNexera
boolean

Hide the legend. The series stay named in the tooltip, the point labels and the table.

Default false
plotLabelNexera
string

Accessible name of the plot group. Translate it.

Default the chart `title`
noDataLabelNexera
string

Text for a missing value in the tooltip and the table. Translate it.

Default No data
hiddenSeriesNexera
readonly string[]

Names of the hidden series (controlled). Pair it with onHiddenSeriesChange.

Default –
defaultHiddenSeriesNexera
readonly string[]

Names of the series hidden at first (uncontrolled).

Default none
onHiddenSeriesChangeNexera
(hidden: readonly string[]) => void

Called with the names of the hidden series when the user toggles a legend entry.

Default –

* Required. React Aria props shown are the ones most apps use; the component accepts the rest of its React Aria props too.

Accessible by default.

Built on React Aria, and covered by the WCAG 2.2 evidence generated on every build.

WCAG 2.2 evidence

9 direct · 1 supporting
  • 1.1.1Non-text ContentLevel A · tested directly
  • 1.3.1Info and RelationshipsLevel A · tested directly
  • 1.4.1Use of ColorLevel A · tested directly
  • 1.4.10ReflowLevel AA · tested directly
  • 1.4.13Content on Hover or FocusLevel AA · tested directly
  • 2.1.1KeyboardLevel A · tested directly
  • 2.1.2No Keyboard TrapLevel A · tested directly
  • 2.3.3Animation from InteractionsLevel AAA · supporting test
  • 4.1.2Name, Role, ValueLevel A · tested directly
  • 4.1.3Status MessagesLevel AA · tested directly

Fits any width.

Nexera components respond to the space they are given. Drag the corner of the frame, or pick a width.

0 px · drag the corner

Styling hooks

Pass className to add Tailwind classes (merged last). State is exposed as data attributes, so you can style it with variants like data-pressed:.

Usage
<ScatterChart className="shadow-sm" />

Used in blocks

No block uses ScatterChart yet.

Related components