# Area charts in your AI client

> Prompts that turn a trend into a stacked or 100% area chart in Bonnard, and the options and limits the product enforces.

Updated: 2026-10-12

Bonnard draws an area chart for a trend over time, and stacks the areas to show a total and its parts.

[Image: A chat with the question "Monthly revenue this year, as an area chart.", three tool calls, and the area chart Bonnard drew: monthly revenue from January to September 2026, September highest]

The examples use Acme, a demo retailer that reports in pounds. Each variant is a few words in the question. A follow-up changes a chart already drawn.

## How an agent draws it

The chat above ran three tools, in this order:

1. `explore_schema` finds the tables and their columns: here `orders`, with `order_date` and `revenue`.
2. `sql_query` runs a read-only query, so the agent can check the numbers first.
3. `render_chart` takes the SQL and the chart options. It runs the query and returns the chart the chat draws.

The `render_chart` call behind the chart above:

```json
{
  "charts": [
    {
      "sql": "SELECT date_trunc('month', order_date) AS month, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2026-01-01' GROUP BY 1 ORDER BY 1",
      "chartType": "area",
      "title": "Revenue by month, 2026 (£k)",
      "encode": { "x": "month", "y": "revenue" },
      "fields": [
        { "name": "month", "label": "Month" },
        { "name": "revenue", "label": "Revenue (£k)", "format": "number" }
      ]
    }
  ]
}
```

A call takes up to 10 charts, shown as a carousel. Each example below shows its one entry. A connected agent reads the full option reference with `explore_docs`, topic `charts/area`.

## Stacked areas

```prompt
Revenue by channel for the last 12 months, as a stacked area.
```

[Image: Monthly revenue as stacked areas, one colour per channel]

```json
{
  "sql": "SELECT date_trunc('month', order_date) AS month, channel, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2025-10-01' GROUP BY 1, 2 ORDER BY 1",
  "chartType": "area",
  "stacking": "stacked",
  "title": "Revenue by channel, by month (£k)",
  "encode": { "x": "month", "y": "revenue", "series": "channel" },
  "fields": [
    { "name": "month", "label": "Month" },
    { "name": "revenue", "label": "Revenue (£k)", "format": "number" }
  ]
}
```

The top edge is each month's total, and each layer is one channel's part of it.

## A share of the total

```prompt
Revenue by channel for the last 12 months, as a share of the total.
```

[Image: Each month's revenue stacked to 100%, one layer per channel, online the largest]

```json
{
  "sql": "SELECT date_trunc('month', order_date) AS month, channel, SUM(revenue) / 1000 AS revenue FROM orders WHERE order_date >= DATE '2025-10-01' GROUP BY 1, 2 ORDER BY 1",
  "chartType": "area",
  "stacking": "stacked100",
  "title": "Revenue share by channel, by month",
  "encode": { "x": "month", "y": "revenue", "series": "channel" },
  "fields": [
    { "name": "month", "label": "Month" },
    { "name": "revenue", "label": "Revenue (£k)", "format": "number" }
  ],
  "axes": { "y": { "title": "Share of revenue" } }
}
```

Each month stacks to 100%, so each layer is that channel's share. The call names the value axis, since a share is not in £k.

## Overlapping areas

```prompt
Weekly revenue for the UK and Germany since July, as overlapping areas.
```

[Image: Weekly revenue for the UK and Germany as two filled areas, Germany's inside the UK's]

```json
{
  "sql": "SELECT week_label AS week, region, revenue / 1000 AS revenue FROM weekly_region_revenue WHERE region IN ('UK', 'Germany') AND week_start >= DATE '2026-06-29' ORDER BY week_start",
  "chartType": "area",
  "xAxisType": "categorical",
  "title": "Weekly revenue, UK and Germany (£k)",
  "encode": { "x": "week", "y": "revenue", "series": "region" },
  "fields": [
    { "name": "week", "label": "Week" },
    { "name": "revenue", "label": "Revenue (£k)", "format": "number" }
  ]
}
```

Without "stacked", each region fills down to zero and the two overlap. Bonnard draws a split this way unless the question says otherwise. Keep overlapping areas to a few series.

## A running total

```prompt
Cumulative revenue this year, by month.
```

[Image: Revenue to date in 2026 as a filled area, rising to £23.3M in September]

```json
{
  "sql": "SELECT month, SUM(revenue) OVER (ORDER BY month) / 1000000 AS revenue FROM (SELECT date_trunc('month', order_date) AS month, SUM(revenue) AS revenue FROM orders WHERE order_date >= DATE '2026-01-01' GROUP BY 1) AS m ORDER BY month",
  "chartType": "area",
  "title": "Revenue to date, 2026 (£m)",
  "encode": { "x": "month", "y": "revenue" },
  "fields": [
    { "name": "month", "label": "Month" },
    { "name": "revenue", "label": "Revenue to date (£m)", "format": "number" }
  ]
}
```

The running total comes from the SQL, a window sum over the months. The area fills under it, so its top edge is revenue to date.

## A target line

```prompt
UK weekly revenue since July as an area, with a line at the £150K target.
```

[Image: UK weekly revenue as a filled area, with a dashed line at the £150K target]

```json
{
  "sql": "SELECT week_label AS week, revenue / 1000 AS revenue FROM weekly_region_revenue WHERE region = 'UK' AND week_start >= DATE '2026-06-29' ORDER BY week_start",
  "chartType": "area",
  "xAxisType": "categorical",
  "title": "UK weekly revenue against target (£k)",
  "encode": { "x": "week", "y": "revenue" },
  "fields": [
    { "name": "week", "label": "Week" },
    { "name": "revenue", "label": "Revenue (£k)", "format": "number" }
  ],
  "reference": [
    { "y": 150, "label": "Target £150K" }
  ]
}
```

Targets, budgets, shaded bands and average or median lines work the same way, up to six on one chart. On a stacked area, an average or median is of the total.

## Options and limits

Table: What an area chart takes

| Ask for | What Bonnard draws |
| --- | --- |
| "stacked" | Series stacked, the top edge the total |
| "as a share of the total" | A 100% stack, each series as its share at every point |
| "overlapping" | Each series filled from zero, the default for a split |
| "cumulative" or "a running total" | A running total from the SQL, filled underneath |
| "with conversion on the right" | A second axis for a measure in other units, drawn as a line |
| "a target line" or "the average" | Reference lines and bands, up to six |
| "a 4-week moving average" or "a trend line" | A dashed line over each series, or over the stack's total |
| "make the UK stand out" | Up to three series highlighted |
| "on a timeline" | Dates spaced by the time between them, the default when unstacked |
| "start the axis at 100" | A fixed axis range, or one fitted to the data |
| "missing months as zero" | Gaps filled with zero or the last value, or left as a break |

- There is no cap on series.
- A chart query returns up to 5,000 rows by default.
- Stacked areas keep one slot per row unless the call asks for a timeline. A 100% stack never takes one.
- In a stack, a missing value counts as zero, so the layers stay aligned.
- Each measure on the left axis is filled. A measure on the right axis sits outside the stack, as a line with no fill.
- A 100% stack has no total, so it takes no moving average or trend line.
- An area whose axis starts above zero says so under the chart.
- Labels and axis titles run to 60 characters.
- Lines run straight between points. An area chart draws no data labels. No chart draws a log scale, custom hex colours or zoom.

## When Bonnard draws something else

- A target that changes month by month comes from the SQL as a measure, and the agent draws it as a line over bars.
