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

ProgressBar

A ratio from 0 to 1 drawn as a filled block-element bar.

A ratio from 0 to 1 drawn as a filled block-element bar.

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

ProgressBar is a determinate bar with a label, a percentage and a fill character.

It is a plain termmosaic.Widget: nothing about a bar is selectable, and a widget that claimed focus would swallow the keys its neighbours needed.

Rendered output

ProgressBar 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 14 × 3 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 × 4 rows

╭ render ──────────────────────────────╮
│generating captures  ███████      62% │
│                                      │
╰──────────────────────────────────────╯

80 columns × 4 rows

╭ render ──────────────────────────────────────────────────────────────────────╮
│generating captures  ███████████████████████████████▌                     62% │
│                                                                              │
╰──────────────────────────────────────────────────────────────────────────────╯

120 columns × 4 rows

╭ render ──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│generating captures  ████████████████████████████████████████████████████████▂                                    62% │
│                                                                                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

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.

# ProgressBar — A ratio from 0 to 1 drawn as a filled block-element bar.
# package: widgets/viz
# constructor: viz.NewProgressBar(r buffer.Rect) *viz.ProgressBar
# 120 columns x 4 rows, rendered through widgettest.Capture

╭ render ──────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│generating captures  ████████████████████████████████████████████████████████▂                                    62% │
│                                                                                                                      │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯

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. Filled with U+2588 FULL BLOCK. The difference between FillStyle and TrackStyle carries an attribute as well as a colour, so the bar is readable without either.

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.NewProgressBar(r buffer.Rect) *viz.ProgressBar

NewProgressBar takes a rect; the ratio is the Ratio field.

  • Ratio — float64 — 0 to 1. Values outside the range are clamped, not an error.
  • Label — []buffer.Span, via SetLabel(s, st) for the common single-run case or SetLabelSpans(spans) for several styled runs. It was an exported field until v0.5.0. A label is a measured region, so a longer one shortens the bar at the same rect — which is why the setters drop the cached budget rather than merely repainting. Read it back with Label(), whose returned slice is the widget’s own and must not be modified.
  • Percentage — bool, via SetPercentage(on) — show the percentage. The number is the reading; the bar is the shape. It was an exported field until v0.5.0; the setter drops the cached budget so the bar re-solves at the same rect. Read it back with Percentage().
  • FillRune — rune — the fill glyph, U+2588 FULL BLOCK by default.
  • FillStyle — buffer.Style — the filled part. The difference from TrackStyle carries an attribute as well as a colour, so the bar is readable with either suppressed.

More on accessibility

Two non-colour signals: the fill character differs from the track character, and the fill and track styles differ by attribute as well as colour. With NO_COLOR set, or on a monochrome terminal, the bar still reads.

When not to use it

Do not use it for work whose completion is unknown. There is no indeterminate mode. A bar that fills toward a target it cannot compute is a lie that resolves to 100% and then stops; if you do not know the denominator, show a Sparkline or a Meter of what you do know, or say nothing.

Do not use it for a bounded measurement. A ProgressBar answers “how far along”; it has no zones, no threshold and no named range. That is Meter, and a progress bar used for a bounded value loses the threshold — the one thing a reader scanning the screen wants.

Do not use it for a value that is not 0-to-1. A percentage that climbs to 400% reads as a bug even when it is correct. Normalise it yourself.

Do not use it as a spinner. It does not animate, and nothing in the catalog does. A busy indicator is yours to draw, and on reflection it is usually better as a label that says what is happening.

Instead: Meter for a bounded reading with zones, Sparkline for a rate over time.