# Scatter Chart

> A composable scatter chart for relationships, clusters, bubbles, and quadrant analysis.

Source: https://www.honestui.com/docs/charts/scatter-chart/static

### Standard Scatter

```tsx
"use client";

import { ScatterChart, type ChartConfig } from "honestui/charts";

// Scenario: Building energy performance
const data = [
  { building: "Harbor Tower", type: "office", floorArea: 96, energyUse: 103 },
  { building: "Maple Center", type: "office", floorArea: 80, energyUse: 87 },
  { building: "Civic Hall", type: "office", floorArea: 106, energyUse: 95 },
  { building: "Union House", type: "office", floorArea: 87, energyUse: 108 },
  { building: "Market Annex", type: "office", floorArea: 69, energyUse: 81 },
  { building: "Roosevelt School", type: "school", floorArea: 40, energyUse: 106 },
  { building: "Lincoln School", type: "school", floorArea: 55, energyUse: 101 },
  { building: "Adams School", type: "school", floorArea: 26, energyUse: 92 },
  { building: "Franklin School", type: "school", floorArea: 34, energyUse: 98 },
  { building: "Jefferson School", type: "school", floorArea: 48, energyUse: 84 },
];

const chartConfig = {
  floorArea: { label: "Licensed floorArea" },
  energyUse: { label: "Energy use" },
  office: {
    label: "Office",
    colors: { light: ["#2563eb"], dark: ["#60a5fa"] },
  },
  school: {
    label: "School",
    colors: { light: ["#059669"], dark: ["#34d399"] },
  },
} satisfies ChartConfig;

export function ExampleScatterChart() {
  return (
    <ScatterChart
      data={data}
      config={chartConfig}
      xDataKey="floorArea"
      yDataKey="energyUse"
      groupDataKey="type"
      pointNameDataKey="building"
      className="h-full w-full p-4"
    >
      <ScatterChart.Grid />
      <ScatterChart.XAxis label="Licensed floorArea" hideDots />
      <ScatterChart.YAxis label="Adoption" hideDots tickFormatter={(value) => `${value}%`} />
      <ScatterChart.Legend isClickable />
      <ScatterChart.Tooltip yValueFormatter={(value) => `${value}%`} />
      <ScatterChart.Scatter dataKey="office" isClickable />
      <ScatterChart.Scatter dataKey="school" isClickable />
    </ScatterChart>
  );
}

```

## Overview [#overview]

Use a scatter chart to inspect relationships between two numeric measures, reveal clusters, and spot outliers. Add bubble sizing when a third measure matters, or divide the plot into labeled quadrants for prioritization and portfolio analysis.

## Anatomy [#anatomy]

`ScatterChart` owns the rows, numeric x/y fields, optional grouping, loading state, and selection. Add one `Scatter` per series, then compose optional `Grid`, `XAxis`, `YAxis`, `Legend`, `Tooltip`, and `Quadrants` parts.

## Accessibility [#accessibility]

Provide a meaningful `ariaLabel` and pair the canvas with a table or written summary when point-level data is essential. Tooltips and direct point selection are pointer-operated, so they cannot be the only source of exact values or the only path to an action. Bubble area and quadrant color should supplement labels and values rather than carry meaning alone.

## Installation [#installation]

<CommandBlock commands="[&#x22;honestui&#x22;]" />

## Usage [#usage]

```tsx
import { ScatterChart, type ChartConfig } from "honestui/charts";
```

```tsx
<ScatterChart
  data={data}
  config={chartConfig}
  xDataKey="seats"
  yDataKey="adoption"
  groupDataKey="segment"
  pointNameDataKey="account"
>
  <ScatterChart.Grid />
  <ScatterChart.XAxis label="Floor area" />
  <ScatterChart.YAxis label="Energy use" />
  <ScatterChart.Legend />
  <ScatterChart.Tooltip />
  <ScatterChart.Scatter dataKey="enterprise" />
  <ScatterChart.Scatter dataKey="startup" />
</ScatterChart>
```

When `groupDataKey` is supplied, each `Scatter` renders rows whose group value matches its `dataKey`. Without grouping, a single series renders every row.

### Bubble Chart [#bubble-chart]

### Bubble Chart

```tsx
"use client";

import { ScatterChart, type ChartConfig } from "honestui/charts";

// Scenario: Wildlife field survey
const data = [
  { species: "Elk", mass: 21, speed: 84, population: 140 },
  { species: "Fox", mass: 36, speed: 63, population: 281 },
  { species: "Bison", mass: 54, speed: 74, population: 480 },
  { species: "Hare", mass: 67, speed: 48, population: 608 },
  { species: "Wolf", mass: 80, speed: 56, population: 889 },
  { species: "Lynx", mass: 92, speed: 37, population: 1147 },
  { species: "Bear", mass: 103, speed: 30, population: 1580 },
  { species: "Deer", mass: 44, speed: 95, population: 386 },
];

const chartConfig = {
  mass: { label: "Body mass" },
  speed: { label: "Top speed" },
  population: { label: "Population" },
  companies: {
    label: "Species",
    colors: {
      light: ["#dbeafe", "#2563eb"],
      dark: ["#1e3a8a", "#60a5fa"],
    },
  },
} satisfies ChartConfig;

export function BubbleScatterChart() {
  return (
    <ScatterChart
      data={data}
      config={chartConfig}
      xDataKey="mass"
      yDataKey="speed"
      pointNameDataKey="species"
      className="h-full w-full p-4"
    >
      <ScatterChart.Grid />
      <ScatterChart.XAxis label="Body mass" hideDots tickFormatter={(value) => `$${value}m`} />
      <ScatterChart.YAxis label="Top speed" hideDots tickFormatter={(value) => `${value}%`} />
      <ScatterChart.Tooltip
        xValueFormatter={(value) => `$${value}m`}
        yValueFormatter={(value) => `${value}%`}
        sizeValueFormatter={(value) => value.toLocaleString()}
      />
      <ScatterChart.Scatter
        dataKey="companies"
        variant="bubble"
        sizeDataKey="population"
        minSize={12}
        maxSize={52}
        isClickable
      />
    </ScatterChart>
  );
}

```

Set `variant="bubble"` and provide `sizeDataKey` to encode a third numeric measure by area. `minSize` and `maxSize` keep small values visible and large values from overwhelming the plot.

### Quadrant Chart [#quadrant-chart]

### Quadrant Chart

```tsx
"use client";

import { ScatterChart, type ChartConfig } from "honestui/charts";

// Scenario: Conservation project planning
const data = [
  { project: "Wetland restoration", cost: 37, habitatGain: 101 },
  { project: "River cleanup", cost: 91, habitatGain: 106 },
  { project: "Forest corridor", cost: 71, habitatGain: 84 },
  { project: "Pollinator garden", cost: 33, habitatGain: 74 },
  { project: "Trail reroute", cost: 81, habitatGain: 44 },
  { project: "Nest boxes", cost: 26, habitatGain: 54 },
  { project: "Invasive removal", cost: 95, habitatGain: 28 },
  { project: "Prairie seeding", cost: 50, habitatGain: 91 },
  { project: "Stream monitoring", cost: 63, habitatGain: 67 },
];

const chartConfig = {
  cost: { label: "Cost" },
  habitatGain: { label: "Habitat gain" },
  initiatives: {
    label: "Projects",
    colors: { light: ["#d97706"], dark: ["#fbbf24"] },
  },
} satisfies ChartConfig;

export function QuadrantScatterChart() {
  return (
    <ScatterChart
      data={data}
      config={chartConfig}
      xDataKey="cost"
      yDataKey="habitatGain"
      pointNameDataKey="project"
      className="h-full w-full p-4"
    >
      <ScatterChart.XAxis min={0} max={100} label="Effort" hideDots />
      <ScatterChart.YAxis min={0} max={100} label="Impact" hideDots />
      <ScatterChart.Quadrants
        xSplit={50}
        ySplit={50}
        labels={{
          topLeft: "Quick wins",
          topRight: "Strategic",
          bottomLeft: "Fill-ins",
          bottomRight: "Reconsider",
        }}
      />
      <ScatterChart.Tooltip
        xValueFormatter={(value) => `${value}/100`}
        yValueFormatter={(value) => `${value}/100`}
      />
      <ScatterChart.Scatter dataKey="initiatives" symbolSize={12} isClickable />
    </ScatterChart>
  );
}

```

Add `Quadrants` with numeric split points and optional labels. Honest UI renders quiet analytical regions behind the points while retaining exact x/y positioning.

### Loading State [#loading-state]

### isLoading='true'

```tsx
"use client";

import { ScatterChart, type ChartConfig } from "honestui/charts";

// Scenario: Loan applications
const data = [{ x: 12, y: 23 }];
const chartConfig = {
  applications: { label: "Applications", colors: { light: ["#2563eb"], dark: ["#60a5fa"] } },
} satisfies ChartConfig;

export function LoadingScatterChart() {
  return (
    <ScatterChart
      data={data}
      config={chartConfig}
      xDataKey="x"
      yDataKey="y"
      className="h-full w-full p-4"
      isLoading
    >
      <ScatterChart.XAxis />
      <ScatterChart.YAxis />
      <ScatterChart.Scatter dataKey="applications" />
    </ScatterChart>
  );
}

```

The loading state preserves the plot dimensions with neutral placeholder points and the shared chart loading treatment.

## API Reference [#api-reference]

<ApiHeading>
  ScatterChart
</ApiHeading>


  ### `data`

type: `TData[]`

Rows containing numeric x/y values and optional group, name, and size fields.

  ### `config`

type: `ChartConfig`

Defines labels and theme colors for series and tooltip measures.

  ### `xDataKey`

type: `keyof TData & string`

Numeric field plotted horizontally.

  ### `yDataKey`

type: `keyof TData & string`

Numeric field plotted vertically.

  ### `groupDataKey`

type: `keyof TData & string`

Field used to divide rows between composed series.

  ### `pointNameDataKey`

type: `keyof TData & string`

Field used as the tooltip heading for each point.

  ### `animation`

type: `boolean` · default: `true`

Enables intro animation unless reduced motion is preferred.

  ### `defaultSelectedDataKey`

type: `string | null` · default: `null`

Series selected on first render.

  ### `onSelectionChange`



void">
    Fires when a clickable point or legend item changes selection.

  ### `onPointClick`



) => void">
    Returns the source row and encoded point values.

  ### `isLoading`

type: `boolean` · default: `false`

Shows neutral placeholder points and a loading label.

  ### `loadingPoints`

type: `number` · default: `14`

Number of loading placeholders.

  ### `ariaLabel`

type: `string`

Accessible name for the canvas chart.

  ### `chartOptions`



">
    Escape hatch merged over generated ECharts options.


<ApiHeading>
  Scatter
</ApiHeading>


  ### `dataKey`

type: `string`

Series identifier and matching 

    `ChartConfig`

     key.

  ### `variant`

type: `&#x22;standard&#x22; | &#x22;bubble&#x22;` · default: `&#x22;standard&#x22;`

Uses a fixed point size or size encoding.

  ### `sizeDataKey`

type: `string`

Numeric field used by the bubble variant.

  ### `symbol`

type: `ScatterSymbol` · default: `&#x22;circle&#x22;`

Point shape.

  ### `symbolSize`

type: `number` · default: `10`

Fixed size for standard points.

  ### `minSize`

type: `number` · default: `8`

Smallest bubble diameter.

  ### `maxSize`

type: `number` · default: `44`

Largest bubble diameter.

  ### `fillOpacity`

type: `number` · default: `0.78`

Point fill opacity.

  ### `isClickable`

type: `boolean` · default: `false`

Enables selection and point click callbacks.

  ### `large`

type: `boolean` · default: `false`

Enables ECharts large-data rendering.

  ### `largeThreshold`

type: `number` · default: `2000`

Point count that activates large rendering.


<ApiHeading>
  Quadrants
</ApiHeading>


  ### `xSplit`

type: `number`

Vertical dividing value.

  ### `ySplit`

type: `number`

Horizontal dividing value.

  ### `labels`

type: `QuadrantLabels`

Labels for the four analytical regions.

  ### `showLabels`

type: `boolean` · default: `true`

Shows quadrant labels.


<ApiHeading>
  XAxis / YAxis
</ApiHeading>


  ### `tickFormatter`



string">
    Formats numeric ticks.

  ### `label`

type: `string`

Axis title.

  ### `hideDots`

type: `boolean` · default: `false`

Hides small tick marks.

  ### `min`

type: `number`

Explicit lower bound.

  ### `max`

type: `number`

Explicit upper bound.


<ApiHeading>
  Tooltip
</ApiHeading>


  ### `variant`

type: `&#x22;default&#x22; | &#x22;frosted-glass&#x22;` · default: `&#x22;default&#x22;`

Tooltip surface treatment.

  ### `roundness`

type: `&#x22;sm&#x22; | &#x22;md&#x22; | &#x22;lg&#x22; | &#x22;xl&#x22;` · default: `&#x22;lg&#x22;`

Tooltip corner radius.

  ### `position`

type: `&#x22;fixed&#x22; | &#x22;variable&#x22;` · default: `&#x22;variable&#x22;`

Pins or follows the active point.

  ### `xValueFormatter`



string">
    Formats the horizontal value.

  ### `yValueFormatter`



string">
    Formats the vertical value.

  ### `sizeValueFormatter`



string">
    Formats the bubble-size value.

  ### `defaultIndex`

type: `number`

Opens a tooltip after mount.


<ApiHeading>
  Legend
</ApiHeading>


  ### `variant`

type: `LegendVariant` · default: `&#x22;circle&#x22;`

Shared Honest UI legend indicator style.

  ### `align`

type: `&#x22;left&#x22; | &#x22;center&#x22; | &#x22;right&#x22;` · default: `&#x22;center&#x22;`

Horizontal alignment.

  ### `verticalAlign`

type: `&#x22;top&#x22; | &#x22;middle&#x22; | &#x22;bottom&#x22;` · default: `&#x22;bottom&#x22;`

Placement around the plot.

  ### `isClickable`

type: `boolean` · default: `false`

Lets legend items isolate a series.
