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/form

Toggle

A two-state switch with an on and an off rendering.

A two-state switch with an on and an off rendering.

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

Toggle is an on/off switch with an optional label.

It is not a Checkbox with a different marker: a toggle means “this is running right now” and a checkbox means “include this in the operation”, and users read them differently. The difference is spelled in the marker — the words “on” and “off” — because a bare “[x]” would be ambiguous between the two.

Rendered output

Toggle 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 6 × 1 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 × 3 rows

[on ] wrap text                         
                                        
                                        

80 columns × 3 rows

[on ] wrap text                                                                 
                                                                                
                                                                                

120 columns × 3 rows

[on ] wrap text                                                                                                         
                                                                                                                        
                                                                                                                        

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.

# Toggle — A two-state switch with an on and an off rendering.
# package: widgets/form
# constructor: form.NewToggle(r buffer.Rect, label string) *form.Toggle
# 120 columns x 3 rows, rendered through widgettest.Capture

[on ] wrap text


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.

Package context

Package form provides the input widgets: TextInput, TextArea, Select, Checkbox, Radio, Toggle, Tabs, Button and KeyHint.

Four rules, each of which is a consequence of something decided elsewhere, and each of which is enforced by this package’s tests rather than by convention:

  • A widget’s space is Bounds(), never buf.Size() (ADR 0007 §1 rule 1).
  • Every widget repaints its entire Bounds() before drawing content, because the renderer diffs and never clears (ADR 0007 §1 rule 3).
  • Draw is total for every rect, including 0×0, 1×1 and anything below MinSize, and it clips rather than blanking (ADR 0007 §4).
  • Nothing derived from the size or from the text is built inside Draw. Wrap, Truncate and span construction allocate, so each widget caches the result against the rect it was computed for and rebuilds when the rect, the text or the styles change (ADR 0007 §3, ADR 0008 §4).

Constructing it

form.NewToggle(r buffer.Rect, label string) *form.Toggle

NewToggle takes the label; the state is a field.

  • Label — string — drawn after the switch.
  • OnStyle — buffer.Style — the on rendering. The on and off states are different marks; OnStyle is decoration on top of that, not the signal.
  • Ascii — bool — [on]/[off] rather than the Unicode switch set.

Key contract

Keys are consumed only while focused. Every binding toggles; there is no “set to on” key, because a toggle has two states and reaching either is the same action.

Keys Effect
toggle KeySpace, KeyEnter, KeyLeft, KeyRight

Accessibility

The state is the WORD: “[on]” or “[off]”, both five cells wide so the label never moves when the state changes. Nothing about the state depends on colour.

When not to use it

Do not use it as a checkbox. It is not a Checkbox with a different marker, and the difference is semantic: a toggle says this is running right now, a checkbox says include this in the operation. Use whichever claim you actually mean.

Do not use it to trigger an action. Toggling changes state; it does not do the thing. If pressing it should start something, that is a Button.

Do not expect the framework to make the change. Handle flips the widget’s own field and invalidates it. If flipping it should start a job, stop a service or write a setting, the application observes that and does it — there is no callback and no event.

Do not use it in a form where the label must be a separate field. The label is drawn inline after the switch, and a two-column form of “label” / “control” is a layout job — see Forms.

Instead: Checkbox for an operation setting, Button for an action.