Widgets widgets/basic
Text
A single line of styled spans, aligned within its rectangle.
A single line of styled spans, aligned within its rectangle.
Package widgets/basic. API reference: pkg.go.dev/widgets/basic.
Text renders styled spans on one line.
It is the smallest widget in the catalog and the one most often composed: a label in a form, a value beside it, a status line. It truncates rather than wraps, because wrapping is Paragraph’s job and a widget that both wrapped and did not would be two widgets.
Rendered output
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() is not in the manifest for this widget, so this page does not
claim a minimum. If you need one, call it.
40 columns × 3 rows
TermMosaic — 22 widgets, 2 dependencies
80 columns × 3 rows
TermMosaic — 22 widgets, 2 dependencies
120 columns × 3 rows
TermMosaic — 22 widgets, 2 dependencies
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.
# Text — A single line of styled spans, aligned within its rectangle. # package: widgets/basic # constructor: basic.NewText(r buffer.Rect, spans []buffer.Span) *basic.Text # 120 columns x 3 rows, rendered through widgettest.Capture TermMosaic — 22 widgets, 2 dependencies
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 basic provides the two text widgets: Text, which writes styled spans on one line, and Paragraph, which wraps them.
Both follow the same two rules, which are the rules every widget in the catalog follows:
- The available space is Bounds(), never buf.Size(). The buffer is the screen; the rect is the widget’s space (ADR 0007 §1 rule 1).
- Nothing derived from the size is built in Draw. Wrap and Truncate both allocate, so Paragraph caches its Wrapped and Text caches its truncation against the rect they were computed for, and recompute only when Bounds() differs (ADR 0007 §3, ADR 0008 §4).
Constructing it
basic.NewText(r buffer.Rect, spans []buffer.Span) *basic.Text
NewText takes the spans up front. Because the span list is parsed once rather than per frame, mutating the slice contents afterwards does not repaint — replace Text.Spans and call Invalidate().
Spans—[]buffer.Span— the styled runs on the line. Parsed once at construction, which is whyDrawallocates nothing.Align—geometry.Align— start, centre or end withinBounds().Ascii—bool— force ASCII for anything that would otherwise need a Unicode glyph.
When not to use it
Do not use it for text that must wrap. Text is one line and truncates with a marker; it will not reflow. Reflowing is Paragraph, and the difference is a real one — reaching for Text with a long string produces a silently truncated label rather than an error.
Do not use it for anything the user can edit. There is no caret and no key contract; it is a display widget. Editing is TextInput.
Do not use it to show a value whose length changes per frame without calling Invalidate(). Text caches its layout against its rect and its spans (ADR 0007 §3); a widget whose setter writes a field Draw reads must invalidate in that setter, or the old text stays on screen permanently. This is the caching bug ADR 0007’s 2026-10-04 amendment is about, and Text is not exempt from it.
Instead: Paragraph to wrap, TextInput to edit.
Related
Paragraph— the same spans, wrapping.- Buffers and cells — what
Spanwrites into. - Responsiveness and the size budget — why
Drawre-derives fromBounds(). - TermMosaic limitations that apply to every widget
- Source:
widgets/basicon GitHub