Distribution Chart
How the values of one measure are spread, as a histogram, box plots or dots.
Pattern · Shares patterns with Chart, Scatter Plot
≈ 1,940 tokens per use (tool 839 · guidance 346 · typical payload 755)How token costs are estimated
Example: Distribution Chart
How long do our deliveries usually take?
How long deliveries take
160 deliveries, last 7 days
- Median
- 32 min
- Middle half
- 29 min – 35 min
- Range
- 22 min – 61 min
- Count
- 160
| Count | Median | Middle half | Range | Outliers |
|---|---|---|---|---|
| 160 | 32 min | 29 min to 35 min | 22 min to 61 min | 45 min, 46 min, 48 min, 48 min, 48 min, 49 min, 50 min, 50 min, 52 min, 53 min, 54 min, 55 min, 55 min, 57 min, 58 min, 61 min |
| Delivery time | Count |
|---|---|
| 20 min to 25 min | 9 |
| 25 min to 30 min | 39 |
| 30 min to 35 min | 69 |
| 35 min to 40 min | 22 |
| 40 min to 45 min | 5 |
| 45 min to 50 min | 6 |
| 50 min to 55 min | 5 |
| 55 min to 60 min | 4 |
| 60 min to 65 min | 1 |
- Marked: Promise at 45 min
A typical delivery takes about half an hour; 15 of 160 ran past the 45-minute promise.
When to use
- The user asks how values are spread: what's typical, how wide the range is, whether there are outliers or a long tail (how long deliveries usually take, how salaries vary by level).
- The user wants to see where one value falls among many (my score against the class, our price against competitors).
When not to use
- You only have averages or totals, not the individual values. Say them in a sentence or use a Chart.
- One measure changes over time. Use a line Chart.
- The question is whether two measures move together. Use a Scatter Plot.
- There are fewer than 5 values. List them.
How the agent should use it
- Pass one row per individual value from the tool result. Never bin, average or round them yourself: the component computes the bins, quartiles and outliers.
- Pick the form for the job:
histogramfor the shape of one set of 30 or more values (a peak, a long tail, two humps).boxto compare spread across 2–6 groups (salary by level, response time by tier).dotsfor up to about 80 values, or when each item matters: every value is a dot, with its name on hover.
- Name the measure in 1–4 words, with
format,currencyorunit. - Add a marker for the user's own value, a target or a limit, at most 3.
- In
summary, say what's typical and how wide the spread is in plain words. Outliers are unusual values, not errors.
Design
- Facts first. For one set of values, a row under the title gives the median, the middle half (first to third quartile), the range and the count. With groups, each row's figures are on hover and in the table.
- Histogram. Bins have a round width (1, 2, 2.5 or 5 × 10ⁿ) and start on a round edge, so ranges read as "30–35 min". Without
bins, the count follows Sturges' rule (about log₂ n + 1, between 5 and 30). Hovering a bar shows its range, count and share. - Box plot. One row per group: the box spans the middle half, the dark line is the median, whiskers reach the furthest values within 1.5 × the box's width, and points beyond them are drawn as hollow outliers, each with its name on hover.
- Dots. Values fall into columns one dot wide and stack outwards from the row's centre line; dots shrink when a stack would outgrow its row.
- Markers are dashed lines across the plot with their label above. The value axis always includes them.
- One neutral colour throughout: groups are told apart by their row label, not by colour.
Accessibility
The SVG is hidden from screen readers. A visually hidden summary table (per group when grouped) gives the count, median, middle half, range and outliers; a histogram adds the count per range, and markers are listed after. Values are formatted with Intl, so they follow the user's locale.
Installation
npx shadcn@latest add https://your-site.com/r/distribution-chart.json
Usage
The Distribution Chart is display-only, so the tool can return immediately:
import { tool } from "ai"
import { distributionChartTool } from "@/components/genui/distribution-chart.schema"
const tools = {
[distributionChartTool.name]: tool({
description: distributionChartTool.description,
inputSchema: distributionChartTool.inputSchema,
execute: async () => ({ shown: true }),
}),
}Render it through the Renderer under show_distribution, or directly:
<DistributionChart {...part.input} status={part.state === "input-streaming" ? "streaming" : "ready"} />Values render as they stream in.
Schema
| Prop | Type | Notes |
|---|---|---|
title | string | The question it answers, e.g. "How long deliveries take" |
description | string? | Scope or source |
type | "histogram" | "box" | "dots" | The form, see above |
measure | { key, label, format?, currency?, unit? } | The values. label is the axis title (32 characters at most); format: number, currency or percent (12.5 means 12.5%) |
group | { key, label? }? | Box and dots only: one row per group, up to 6 in first-seen order |
name | string? | Field naming each item, shown on hover in dots and for box outliers |
bins | number? | Histogram only: about how many bars, 5–40 |
markers | { value, label }[]? | Up to 3 reference lines, e.g. "Your time" or "Target" |
data | Record<string, string | number>[] | Data-bound. 5–1000 rows, one per individual value |
summary | string? | One-sentence takeaway, shown under the chart |
Host props: status (streaming or ready) and className.