Radio

May 14, 2026 · View on GitHub

Vertical radio-button group — mutually-exclusive selection where every option is shown on its own row.

Constructor: NewRadio(id, class string, args ...string) *Radio

args are alternating value/label pairs: value1, label1, value2, label2, ... The interface mirrors Select; the difference is purely visual: Radio always shows the full list rather than hiding it behind a dropdown.

Methods

  • Select(value string) — selects option by value (silent — no EvtChange)
  • Text() string — returns display label of selected option
  • Value() string — returns value of selected option
  • Summary() stringselected="..." for Dump output

Keyboard

KeyAction
Up / kSelect previous option (clamps)
Down / jSelect next option (clamps)
HomeSelect first option
EndSelect last option

There is no separate cursor — every navigation key changes the selection immediately and dispatches EvtChange.

Mouse

Left-click on a row selects that option.

Events

EventDataDescription
"change"stringSelected value changed

Select() is silent so programmatic initialisation does not fire handlers; keyboard and mouse interaction always fire EvtChange.

Theme strings

The glyphs are configurable per theme — both can be any rune width (3 cells for (•)/( ), 1 cell for /, or Nerd Font codepoints). The widget pads the narrower glyph so labels stay column-aligned.

KeyDefaultNotes
radio.on(•)Glyph for the selected row
radio.off( )Glyph for unselected rows

Override via theme.SetStrings(...) or by registering the alternate string set (AddUnicodeStrings ships /; AddNerdStrings uses Nerd Font circle glyphs).

Style selectors

SelectorPurpose
radioBase row style for unselected options
radio:disabledWhole widget when disabled
radio:focusedUnselected rows when the widget has focus
radio:hoveredHover state
radio/selectedSelected row (widget unfocused)
radio/selected:focusedSelected row when the widget has focus

Notes

  • Flags: "focusable"
  • Hint height = number of options; width = longest label + 4 (prefix budget)
  • Readonly or Disabled widgets ignore keyboard and mouse input

Example

NewBuilder(themes.TokyoNight()).
    Radio("size", "s", "Small", "m", "Medium", "l", "Large").
    On("change", func(w core.Widget, _ core.Event, data ...any) bool {
        fmt.Println("size:", data[0].(string))
        return true
    })

Composition API:

Radio("size", "", []string{"s", "Small", "m", "Medium", "l", "Large"},
    On(z.EvtChange, func(_ c.Widget, _ z.Event, data ...any) bool {
        fmt.Println("size:", data[0].(string))
        return true
    }),
)