---
name: chart-selection
description: >-
  Which adia-ui component renders a chart, graph, sparkline, gauge, or
  heatmap, and how to wire its data/legend/theming. Use for "add a chart",
  "show a graph", "visualize this data", "add a sparkline/gauge/heatmap", or
  "wire a chart legend". NOT for the surrounding screen (screen-composition),
  color tokens (token-selection), or data fetching (data-wiring).
disable-model-invocation: false
user-invocable: false
---

# chart-selection — chart & graph component usage

`<chart-ui>` is the single declarative SVG chart primitive — 18 types behind one `type`
attribute, one data shape, one event contract. `<chart-legend-ui>` and `<heatmap-ui>` are its
two chart-family siblings. This pack answers "which component/prop/wiring" for chart-shaped
asks; it never composes the screen around the chart.

`<chat-thread-ui>` is unrelated despite the name collision with "chart" — it belongs to the
chat/messaging family, not the chart family. Don't route chat-shaped asks here.

## Which component for which need

| Need | Component | `type` / notes |
| --- | --- | --- |
| bar/line/pie/donut/radar/area/scatter/gauge/funnel/treemap/sankey/composed | **chart-ui** | `type="…"` — full 18-type map: [chart-type-catalog.md](references/chart-type-catalog.md) |
| a keyboard-toggleable series legend beside a chart | **chart-legend-ui** | `[for]` id-ref auto-mirrors **chart-ui only** (heatmap-ui never populates `.legendData`); `items=` for standalone |
| calendar/contribution grid or density matrix | **heatmap-ui** | `type="day-grid"`\|`matrix`\|`density` — NOT chart-ui. Legend equivalent is its built-in Less/More strip (`no-legend` to hide), not `chart-legend-ui` |
| a single prominent KPI number (+ delta, + optional mini-chart) | **stat-ui** | not itself a chart; composes `<chart-ui type="sparkline" slot="chart">` + `[bleed]` |
| a labeled completion bar/percentage, not a plotted series | **progress-ui** | boundary case — stat.yaml: "stat for standalone metrics, progress for completion bars" |

Full type-by-type mapping is in [chart-type-catalog.md](references/chart-type-catalog.md) —
consult before picking a `type` beyond the five common cases above.

## Data binding — the shared shape (except Sankey)

Most `chart-ui` types consume an array of plain objects, keyed by the `x` and `y` attributes —
**not** the Chart.js `{labels, datasets}` envelope (worked example:
[chart-type-catalog.md](references/chart-type-catalog.md)). `type="sankey"` is the exception:
it ignores `x`/`y`, expecting flow-link rows shaped `{ source, target, value }` instead.

- `.data` (JS property) is the canonical entry point; a declarative `data='[…]'` attribute is
  also accepted, hydrated once at connect (static-HTML demos).
- `y` is comma-separated for multi-series types (`y="revenue,users"` → `stacked-bar`/
  `grouped-bar`/`multi-line`/`composed`); single-series types read only the first key.
- A non-array (Chart.js envelope, `null`, object) silently coerces to `[]` — a blank chart with
  a one-shot console warning, not a thrown error. Chart renders empty? Check the data shape.
- Past ~5,000 rows, perf degrades (full-SVG re-render per `.data` write) — downsample before
  setting `.data`, or raise `--chart-perf-budget` for a deliberate large render.

## Composition patterns

- **Chart + legend, auto-wired**: give the chart an `id`, point the legend's `[for]` at it —
  toggling a legend row hides/dims that series in the chart, no manual event wiring needed.
  ```html
  <chart-ui id="rev" type="multi-line" x="month" y="revenue,users"></chart-ui>
  <chart-legend-ui for="rev" shape="line" position="bottom"></chart-legend-ui>
  ```
- **Standalone legend**: `items='[{"key":"revenue","label":"Revenue","slot":0}, …]'` when no
  chart-ui sibling exists, or the legend represents a chart rendered elsewhere.
- **KPI card with inline trend**: `<stat-ui bleed>` + a `<chart-ui slot="chart" type="sparkline">`
  child — value/label/change stack left, chart bleeds the card's right column.
- **Dashboard grid**: `<stat-ui>` cards for KPIs + `<chart-ui>` cards for trend detail via
  `Grid`/`Card` (chart.yaml's `chart-dashboard` example is the canonical a2ui shape) —
  screen-level layout is `screen-composition`'s job, not this pack's.
- **Empty state / loading**: `slot="empty"` (typically `<empty-state-ui>`) replaces the SVG on
  empty/unset `.data`, CSS-toggled via `[data-has-data]`; `loading` prop swaps in a
  `skeleton-ui` placeholder (parity with `table-ui`/`stat-ui`). Neither needs imperative code.
- **Hover/tooltip**: `chart-ui`/`heatmap-ui` share the `chart-hover`/`chart-leave`/`chart-select`
  event trio — wire one shared `tooltip-ui[follows="pointer"][for]` instead of a per-kind
  listener. Full payload shapes + a11y/keyboard contract:
  [composition-and-theming.md](references/composition-and-theming.md).

## Theming & responsive — framework-level conventions

- **Never a raw color.** `color="accent|success|warning|danger|info"` picks the intent palette;
  per-series identity colors come from the 10-slot categorical ramp (`--chart-0`…`--chart-9`) —
  recolor one named series via `--color-{key}` at any ancestor; never hand-write a hex/`oklch()`.
- **Number formatting** is a prop: `format="abbr|decimal|currency|percent"`.
- **Responsive by container, not viewport** — width from `ResizeObserver`, height from a 4:3
  ratio unless set explicitly; `--chart-max-height` (default `28rem`) caps runaway heights.
  Never wrap in a fixed-pixel container to "make it responsive" — size the parent instead.

Token roster, per-series override mechanics, keyboard/a11y contract, and the full event-payload
shapes: [composition-and-theming.md](references/composition-and-theming.md).

## Consult table

| Ask | Answer from |
| --- | --- |
| "which chart-ui type for X" | [chart-type-catalog.md](references/chart-type-catalog.md) |
| "how do I color/theme a chart" | Theming section, then [composition-and-theming.md](references/composition-and-theming.md) |
| "wire a legend to a chart" | Composition patterns above |
| "chart renders blank" | Data binding — check the `.data` shape first |
| "chart-ui vs heatmap-ui vs stat-ui" | Which-component table above |
| "build the whole dashboard screen" | `screen-composition` — per-chart usage only, not screen composition |
| "which token/color role" (beyond chart identity ramp) | `token-selection` |
| "fetch/hydrate the chart's data" | `data-wiring` |
