Scatter Plot

Two measures plotted against each other, with groups, bubbles, a trend line and labelled highlights.

Pattern · Shares patterns with Chart

≈ 2,022 tokens per use (tool 1,165 · guidance 344 · typical payload 513)How token costs are estimated

Example: Scatter Plot

Did ad spend drive signups this quarter? Break it down by channel.

Ad spend vs signups

19 campaigns, Q3

SignupsAd spend
Ad spend vs signups
NameChannelAd spendSignups
Brand termsSearch$4,200610
Competitor termsSearch$6,800540
Pricing pageSearch$3,100420
Free trialSearch$5,600700
IntegrationsSearch$2,400260
TemplatesSearch$1,800230
Spring launchSocial$7,400640
Founder storySocial$2,900300
Customer clipsSocial$4,100430
RetargetingSocial$3,600520
LookalikesSocial$5,200470
Creator collabSocial$6,100360
Webinar promoSocial$1,500170
ExplainerVideo$8,200590
Product tourVideo$5,900510
TestimonialsVideo$3,300280
How-to seriesVideo$4,700450
Pre-roll testVideo$2,200120
Year in reviewVideo$6,600560

Trend: strong positive relationship, r = 0.79.

More spend mostly meant more signups. Creator collab and the pre-roll test returned far less than their spend suggests.

When to use

  • The user asks whether two measures are related: does spend drive signups, are pricier products rated higher, do longer calls close more deals.
  • The user wants to spot outliers or clusters across many items measured two ways.

When not to use

  • One measure changes over time. Use a line Chart.
  • You compare a few categories on one measure. Use a bar Chart.
  • There are fewer than 5 items. Compare them in a Data Table or a sentence.
  • You don't have the figures from a tool. Never invent or estimate points.

How the agent should use it

  • Copy data from the tool result unchanged, one row per item.
  • Put the driver on x and the response on y: spend on x, signups on y.
  • Name both axes in 1–4 words, with format, currency or unit so values read correctly. The titles are shown: the y title above its axis, the x title under the end of its axis, never rotated.
  • Add size only for a third measure that matters (a bubble chart), like review count behind a rating. Never to decorate.
  • Group by a category only when it explains the pattern. Up to 3 groups; a fourth and beyond fold into "Other".
  • Set trend only when the relationship is the question and there are 5 or more points. The legend then names its strength from Pearson's r ("strong positive, r = 0.82"). Correlation is not cause: say "move together", not "causes".
  • Highlight at most 5 points by name (outliers, the user's own item), and say why in summary.

Design

  • Groups differ by colour and shape: vermilion, cool blue and cassis (the first three categorical colours, the only ones that stay distinct for every pair, in both themes) with circle, square and triangle; a fourth group and beyond fold into a neutral grey "Other" (diamond). A single set of points keeps the one-hue tone. A legend appears with two or more groups.
  • Bubbles scale by area, not radius, so a point with twice the value looks twice as big. They're slightly translucent so overlaps stay visible, and every point has a ring in the card colour to keep neighbours apart.
  • The trend line is a dashed straight line across the points' range. With fewer than 5 points, or when either measure doesn't vary, no line is drawn.
  • Highlighted points carry their name beside them; every other point shows its name, group and values on hover. Small points have a larger invisible hover target.

Accessibility

The SVG is hidden from screen readers. A visually hidden table carries every point (name, group, both measures and size), captioned with the title, followed by the trend in words when there is one. Values are formatted with Intl, so they follow the user's locale.

Installation

npx shadcn@latest add https://your-site.com/r/scatter-plot.json

Usage

The Scatter Plot is display-only, so the tool can return immediately:

app/api/chat/route.ts
import { tool } from "ai"
import { scatterPlotTool } from "@/components/genui/scatter-plot.schema"

const tools = {
  [scatterPlotTool.name]: tool({
    description: scatterPlotTool.description,
    inputSchema: scatterPlotTool.inputSchema,
    execute: async () => ({ shown: true }),
  }),
}

Render it through the Renderer under show_scatter, or directly:

<ScatterPlot {...part.input} status={part.state === "input-streaming" ? "streaming" : "ready"} />

Points render as they stream in.

Schema

PropTypeNotes
titlestringThe question it answers, e.g. "Ad spend vs signups". Also the data table's caption
descriptionstring?Scope or source
x, y{ key, label, format?, currency?, unit? }The two measures. label is the axis title (32 characters at most); format: number, currency or percent (12.5 means 12.5%)
size{ key, label, format?, currency?, unit? }?A third measure sizing the points: a bubble chart
namestring?Field naming each point, shown on hover and used by highlight
group{ key, label? }?Category splitting the points; up to 3 coloured groups, more fold into "Other"
highlightstring[]?Up to 5 point names to label on the chart
trendboolean?Best-fit line and correlation strength; needs 5 or more points
dataRecord<string, string | number>[]Data-bound. 3–500 rows with the x and y keys, plus size, name and group keys when used
summarystring?One-sentence takeaway, shown under the chart

Host props: status (streaming or ready) and className.

Source

On this page