# chart — behaviour

*Open when you are putting a chart, a KPI tile or a dashboard of them on a form.*

**An incomplete source renders the built-in DEMO series — plausible bars, no error, no gate finding.** Complete means every part at once:

```jsonc
"dataSource": { "kind": "entity", "entity": "Deals", "categoryField": "stage.name",
  "values": [{ "id": "m1", "field": "totalAmount", "aggregation": "sum" }] }
```

A `kind: 'formula'` row does not count as the measure; a `kpi` tile needs no `categoryField`. Write `sqlQuery` while `kind` stays `'entity'` and every `sql*` key is ignored — demo bars again (`'suppaSql'` is inferred only when `entity` is absent).

**Demo data is the mild failure; blank is the other one.** A measure `field` written as a label (`"Total Amount"` for `totalAmount`) makes the aggregate request fail and the chart sticks in its error state. `kpiCompareText`, `centerTotalText` and `emptyText` are plain strings, not `{ en, uk }` objects: `kpiCompareText` is read through `String.trim`, so an object throws and the whole tile renders nothing, on the builder canvas too.

**Nothing sizes a chart.** It is the one large widget deliberately left out of full-width widening and the 6-row floor (a KPI is a 3-column cell, dashboards go 2-up), so `layout.lg.height: 1` ships one row tall. `containerSettings` is seeded only while you omit it — 400px, or 140px + `widthMode: 'fill'` for `kpi`. What you write is kept verbatim, so a hand-sized 400px KPI ships 2.9× the design height.

**Right-looking, wrong question.** `limit: 10` alone takes the first ten of the alphabetical category order — "top 10" is `sortBy: 'value'` + `sortOrder: 'desc'` + `limit`, and `'value'` silently falls back to category order under `seriesField`. `categoryDateGranularity` buckets by date PART, so `quarter` merges Q1 2025 with Q1 2026. `chartType: 'pie'` draws a donut until `donut: false`. A `gauge` plots only the first value of the first series against `gaugeMax`, whose 200 is a mock-era placeholder. Money is stored in minor units and the chart is the one renderer that does not divide by 100 — `style: 'currency'` picks the symbol only, so add `centsToUnits: true`.

**Live vs frozen.** An `html` stat tile is a hard-coded number; a tile whose value is an aggregate is `chartType: 'kpi'`. `kpiSparkline: true` without a `categoryField` (or `sqlCategoryColumn`) is one bucket, so the line never draws — and that warning is builder-only.
