# Charts

Vee draws six kinds of chart, and a plugin reaches them through three different
output formats. This page is the index: what exists, how to emit it, and what
each one takes. The prose that explains any given chart lives with its surface —
[Plugin authoring](plugin-authoring.md) for the menu bar, [Widgets](widgets.md)
for the desktop — and each row below links into it.

Every chart is drawn natively. There is no WebView anywhere in Vee, and no
charting library: an inline chart is an AppKit or SwiftUI row view, a popover is
Swift Charts, and a widget is WidgetKit.

## The matrix

<!-- Generated by docs/scripts/build_reference.py from docs/api/params.json. Do not edit; edit the JSON and re-run. -->

**Where each chart comes from.** The same chart is spelled differently depending on which output format a plugin uses; a dash means that surface cannot draw it.

| Chart | Text protocol | JSON menu output | Widget card |
| ----- | ------------- | ---------------- | ----------- |
| **Sparkline** — A line/area series over time. | `sparkline=1,2,3` | `"sparkline": [1,2,3]` | `node type "sparkline" with "values", or the "trend" template's "trend"` |
| **Progress bar** — One capsule bar filled to a fraction. | `progress=0.72 or progress=23.65,100` | `"progress": 0.72` | `"progress" on the card, the "gauge" template's fill` |
| **Pie** — A filled circle divided into sectors. | `pie=45,30,25` | `"chart": {"kind": "pie", "values": […]}` | — |
| **Donut** — A pie with the middle punched out; the hole carries the total. | `donut=512,256,128` | `"chart": {"kind": "donut", "values": […]}` | — |
| **Stacked bar** — One horizontal bar whose segments lie end to end. | `stackedbar=60,25,15` | `"chart": {"kind": "stackedbar", "values": […]}` | — |
| **Widget gauge** — A native WidgetKit gauge. | — | — | `node type "gauge" with "value", or the "gauge" template` |

**What each chart takes.** One pair sizes any of them: `accessoryw=` and `accessoryh=`, whichever accessory the row carries. The per-chart names (`sparklinew=`, `chartw=`, `progressw=` and their heights) still parse but are deprecated, and do nothing when aimed at a chart the row does not draw.

| Chart | Options | Default size | Full width | Limits | Click |
| ----- | ------- | ------------ | ---------- | ------ | ----- |
| **Sparkline** | `sparklinew`, `sparklineh`, `sparklinecolor`, `accessory`, `color` | 90×20 points | `accessoryw=full` | Widget sparkline nodes are truncated at 256 points; non-finite entries are dropped. | Yes — a full Swift Charts line/area chart. |
| **Progress bar** | `progressw`, `progressh`, `progresstrackcolor`, `accessory`, `color` | 120×6 points | `accessoryw=full` | Clamped to 0…1; a non-finite value is dropped. | No — the bar is the whole surface. |
| **Pie** | `chartw`, `charth`, `chartlabels`, `chartcolors`, `accessory` | 24pt diameter | Not supported — refused with a diagnostic. | 8 segments (the tail folds into 'Other'); size clamped to 8–200 points. | Yes — full size with a labelled legend. |
| **Donut** | `chartw`, `charth`, `chartlabels`, `chartcolors`, `accessory` | 24pt diameter | Not supported — refused with a diagnostic. | 8 segments (the tail folds into 'Other'); size clamped to 8–200 points. | Yes — full size with a labelled legend. |
| **Stacked bar** | `chartw`, `charth`, `chartlabels`, `chartcolors`, `accessory` | 110×12 points | `accessoryw=full` — the only chart kind that accepts it. | 8 segments (the tail folds into 'Other'); size clamped to 8–200 points. | Yes — full size with a labelled legend. |
| **Widget gauge** | `gauge_style`, `style.tint` | gauge_style: linear | Not applicable — a circular gauge takes no size knob. | value clamped to 0…1. | No — widgets have no popover surface. |


## Where a chart appears

A menu-bar chart occupies the row's **accessory slot** — the same slot for all
of them, which is why a row draws one chart and not three. When a line carries
more than one, the last one wins in the order `progress=` → `sparkline=` →
share chart. `accessory=leading` moves it to the other edge of the row.

Most of them are also clickable. A sparkline or a share chart opens a Liquid
Glass popover with the same data at full size — the legend that `chartlabels=`
feeds is only visible there, since a menu row has no room for it. A progress bar
has no popover: the bar already shows everything it has.

## Sizing

Each chart is sized by knobs named after itself:

| Chart | Width | Height | Stretch to the row |
| ----- | ----- | ------ | ------------------ |
| Sparkline | `accessoryw=` | `accessoryh=` | `accessoryw=full` |
| Progress bar | `accessoryw=` | `accessoryh=` | `accessoryw=full` |
| Pie, donut | `accessoryw=` or `accessoryh=` — either sizes both | | not supported |
| Stacked bar | `accessoryw=` | `accessoryh=` | `accessoryw=full` |
| Slider | `accessoryw=` | — its height is its control size | not supported |

`full` stretches a chart to the width the row actually has, rather than a fixed
number of points. It exists because a menu is as wide as its widest row, so a
fixed width cannot fill a menu whose width some *other* row decides. It applies
only to charts with free width: a pie and a donut are circles, whose width *is*
their diameter, so stretching one would make the row as tall as the menu is
wide. Vee refuses it there and says so in a diagnostic rather than guessing.

## Choosing one

- A value **over time** — load average, request rate, temperature — is a
  sparkline.
- A single value **against a maximum** — disk used, battery, quota — is a
  progress bar, or a gauge in a widget.
- A total that **divides into categories** — disk by folder, spend by
  department — is a share chart. Pie, donut, and stacked bar read the same
  numbers and differ only in shape, so switching between them needs no change
  to the values, labels, or colors.

Share charts carry at most eight segments, because the categorical palette has
eight slots and a ninth would have to reuse a hue — exactly the ambiguity a
share chart must not have. A longer series is **folded, not truncated**: the
leading segments are kept and the rest are summed into a final `Other`, so the
shares still add up to the plugin's own total.

## Colors

A share chart's segments take a fixed eight-slot categorical palette, assigned
in order and never cycled — slot *n* always means "the nth segment", so a series
that shrinks does not repaint the segments that survived. Each slot is a
light/dark pair chosen against its own mode's background rather than one color
flipped, and the set is validated for colorblind separation including the
first-to-last pair, which a pie makes adjacent by wrapping around.

`chartcolors=` overrides it positionally, and a blank or unrecognised entry
keeps that segment's palette slot rather than shifting every later color left —
so `chartcolors=,,red` recolors only the third segment.

Color is never the only channel: every chart carries an accessibility summary
reading its segments and their shares aloud, so the data survives for a reader
who cannot see the difference.

## See also

- [Plugin authoring](plugin-authoring.md#rich-inline-charts-liquid-glass-popovers)
  — the menu-bar charts in full, with worked examples.
- [Widgets](widgets.md) — the gauge and sparkline layout nodes, and the `trend`
  and `gauge` templates.
- [JSON output](json-output.md) — the structured spelling of every chart.
- [Plugin SDKs](sdk.md) — emitting charts from TypeScript, Python, or Go.
