TermMosaic v1.0.0

v1.0.0 is the first release that makes a stability promise: the public API freezes here and Semantic Versioning applies in earnest — with one documented exception: widgets/widgettest is excluded from that promise, because it must evolve with the framework. Read the limitations before you rely on anything here.

Widgets widgets/viz

BarChart

Categorical magnitudes as horizontal or vertical bars, with an axis and per-bar values.

Categorical magnitudes as horizontal or vertical bars, with an axis and per-bar values.

Package widgets/viz. API reference: pkg.go.dev/widgets/viz.

BarChart is a categorical bar chart, vertical or horizontal, with an axis and value labels.

It is a plain termmosaic.Widget: a chart is not selectable.

Rendered output

BarChart rendered by cmd/capture through widgettest.Capture: colour at 3 widths (40, 80, 120 columns), and the exact plain-text cell grid at the widest of them.

MinSize() returns 8 × 6 cells. That is the whole widget including its own chrome, and it is the widget's assertion about itself — below it, Draw clips rather than blanks, and what to do about that is the application's decision.

40 columns × 11 rows

╭ allocations per frame ───────────────╮
│  412     968     1284   2140    356  │
│                        █             │
│                        █             │
│                ▃       █             │
│        ▂       █       █             │
│        █       █       █             │
│▄       █       █       █      ▂      │
│█       █       █       █      █      │
│-buffer--render-widgets-headle…-input-│
╰──────────────────────────────────────╯

80 columns × 11 rows

╭ allocations per frame ───────────────────────────────────────────────────────╮
│      412             968             1284           2140            356      │
│                                                █                             │
│                                                █                             │
│                                ▃               █                             │
│                ▂               █               █                             │
│                █               █               █                             │
│▄               █               █               █              ▂              │
│█               █               █               █              █              │
│-----buffer----------render---------widgets--------headless---------input-----│
╰──────────────────────────────────────────────────────────────────────────────╯

120 columns × 11 rows

╭ allocations per frame ───────────────────────────────────────────────────────────────────────────────────────────────╮
│          412                     968                     1284                   2140                    356          │
│                                                                        █                                             │
│                                                                        █                                             │
│                                                ▃                       █                                             │
│                        ▂                       █                       █                                             │
│                        █                       █                       █                                             │
│▄                       █                       █                       █                      ▂                      │
│█                       █                       █                       █                      █                      │
│---------buffer------------------render-----------------widgets----------------headless-----------------input---------│
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

Plain text — the exact cell grid, trimmed per line. This is the honest form: Braille and block-element glyphs can take a different advance width in a web font than a terminal gives them, which breaks the alignment they depend on.

# BarChart — Categorical magnitudes as horizontal or vertical bars, with an axis and per-bar values.
# package: widgets/viz
# constructor: viz.NewBarChart(r buffer.Rect) *viz.BarChart
# 120 columns x 11 rows, rendered through widgettest.Capture

╭ allocations per frame ───────────────────────────────────────────────────────────────────────────────────────────────╮
│          412                     968                     1284                   2140                    356          │
│                                                                        █                                             │
│                                                                        █                                             │
│                                                ▃                       █                                             │
│                        ▂                       █                       █                                             │
│                        █                       █                       █                                             │
│▄                       █                       █                       █                      ▂                      │
│█                       █                       █                       █                      █                      │
│---------buffer------------------render-----------------widgets----------------headless-----------------input---------│
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

What you are looking at. This is the cell grid the renderer produced, in a web page. It is not a screenshot of a terminal, and it cannot show interaction, resize or animation — a capture is one settled frame after N frames of settling. Braille and Block Elements can take a different advance width in your browser's font than in a terminal, so if a gauge or a sparkline above looks wrong, the plain-text form below it is the exact output and the colour one is the decoration. The colour frames are at 40, 80, 120 columns; the plain-text frame is at 120. More on this.

About this capture. Bars are Block Elements. The value beside each bar is the colour-independent reading and the capture keeps it.

Package context

Package viz provides the catalog’s measurement and display widgets: ProgressBar, Gauge, Meter, Sparkline and BarChart.

  • Its space is Bounds(), never buf.Size() (ADR 0007 §1 rule 1).
  • It repaints its whole Bounds() before drawing content (rule 3), by composing widgets/block.Block, whose Draw fills the rect in Background before anything else. No widget here draws a border, a corner or a title itself.
  • Its Draw is allocation-free (ADR 0008 §4). Everything derived from the size — which regions survived the budget, where the axis labels go, the glyph ramp for a sparkline — is computed in the size-change check, cached against the rect, and only read in Draw.

Constructing it

viz.NewBarChart(r buffer.Rect) *viz.BarChart

NewBarChart takes a rect; Data is a slice of Datum, each a label and a magnitude.

  • Data — []Datum — label plus value per bar.
  • Vertical — bool — bars grow upward. Horizontal is the default and the better fit for a narrow terminal.
  • Max — float64 — the scale ceiling. It defaults to the data’s own maximum, which means the tallest bar always fills the plot; set it when the bars must be comparable to something else.
  • ShowValue — bool — print the value beside each bar. That number is the colour-independent reading.
  • Axis — bool — draw the axis line.

More on accessibility

Each bar carries its value as text beside it, and the label is drawn regardless of colour. A reader who cannot distinguish two bar colours can still read every number. A horizontal category label is clipped to its own column. A label wider than its column is cut rather than allowed to overwrite the next category’s, so keep the labels short — or read the values, which are always printed beside the bars. Fixed in v0.5.1.

When not to use it

Do not use it for a series over time. Time is ordered and a bar chart is not; consecutive bars invite reading a trend that the data does not contain. A series is a Sparkline.

Do not use it when the values are close together and the differences matter. Bars encode magnitude by length from a common baseline, and that is exactly the encoding that hides small differences. Print the numbers, or use a different question.

Do not use it vertically in a short terminal. Vertical bars spend height on the plot and put the labels in the worst place. Horizontal is the default for a reason.

Do not use it with dozens of categories. A bar needs horizontal room for its label. Past roughly a dozen, a Table of names and numbers is both more readable and sortable, and it is what a user will want to do next.

Do not use it to show one value. That is Gauge or ProgressBar.

Instead: Sparkline for time, Table for many categories, Meter for one bounded reading.