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 for the menu bar, Widgets 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
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 — the menu-bar charts in full, with worked examples.
- Widgets — the gauge and sparkline layout nodes, and the
trendandgaugetemplates. - JSON output — the structured spelling of every chart.
- Plugin SDKs — emitting charts from TypeScript, Python, or Go.