Skip to content

Widgets Input

mike-ward edited this page Jun 14, 2026 · 2 revisions

Input Widgets

Input widgets collect text, numbers, dates, and colors from the user. All are keyboard accessible and IME-aware. IDFocus assigns a tab-order position; any positive integer works, and lower numbers are focused first.

For an interactive reference run go run ./examples/showcase/ and select any input entry from the sidebar.


Input (text field)

gui.Input(gui.InputCfg{...}) is the single-line text field. It handles plain text, masked input, and multiline editing.

gui.Input(gui.InputCfg{
    ID:          "search",
    IDFocus:     1,
    Sizing:      gui.FillFit,
    Placeholder: "Enter text...",
    Text:        app.Query,
    SpellCheck:  true,
    OnTextChanged: func(_ *gui.Layout, s string, w *gui.Window) {
        gui.State[App](w).Query = s
    },
})

Key fields:

Field Description
Text Current string value
Placeholder Hint text shown when empty
IsPassword Masks characters
SpellCheck Enables OS spell checking
Multiline Allows newlines; grows vertically
OnTextChanged Called on every keystroke
OnTextCommit Called on Enter or focus loss

Masking modes — Input handles phone numbers and credit card expiry with MaskPhone and MaskExpiry on the Mask field. Characters are formatted automatically as the user types.


NumericInput

gui.NumericInput(gui.NumericInputCfg{...}) restricts entry to numbers, with locale-aware formatting, configurable decimal places, and optional min/max bounds.

gui.NumericInput(gui.NumericInputCfg{
    ID:       "price",
    IDFocus:  2,
    Mode:     gui.NumericCurrency,
    Decimals: 2,
    Min:      gui.Some(0.0),
    Max:      gui.Some(10000.0),
    Text:     app.PriceText,
    Value:    app.PriceValue,
    Width:    220,
    Sizing:   gui.FixedFit,
    OnTextChanged: func(_ *gui.Layout, text string, w *gui.Window) {
        gui.State[App](w).PriceText = text
    },
    OnValueCommit: func(_ *gui.Layout, value gui.Opt[float64], text string, w *gui.Window) {
        a := gui.State[App](w)
        a.PriceValue = value
        a.PriceText = text
    },
})

Key fields:

Field Description
Mode NumericDefault, NumericCurrency, NumericPercent
Decimals Number of decimal places
Min / Max Optional bounds (gui.Some(v) to set)
Locale Override DecimalSep and GroupSep for non-default locales
OnTextChanged Called on every keystroke (raw text)
OnValueCommit Called on Enter or blur; receives parsed Opt[float64]

Two callbacks serve different purposes: OnTextChanged keeps the display text in sync while the user is typing; OnValueCommit fires only when the user finalises the value and gives you the parsed number.


Slider

gui.Slider(gui.SliderCfg{...}) renders a draggable track for selecting a value within a range.

gui.Slider(gui.SliderCfg{
    ID:      "volume",
    IDFocus: 3,
    Min:     0,
    Max:     100,
    Value:   app.Volume,
    Sizing:  gui.FillFit,
    OnChange: func(_ *gui.Layout, value float64, w *gui.Window) {
        gui.State[App](w).Volume = value
    },
})

The OnChange callback fires continuously while dragging.


DatePicker

gui.DatePicker(gui.DatePickerCfg{...}) renders an inline calendar widget. It supports single and multi-date selection.

gui.DatePicker(gui.DatePickerCfg{
    ID:             "cal",
    IDFocus:        4,
    Dates:          app.SelectedDates,
    SelectMultiple: true,
    OnSelect: func(dates []time.Time, _ *gui.Event, w *gui.Window) {
        gui.State[App](w).SelectedDates = append([]time.Time(nil), dates...)
    },
})

For a compact inline entry use InputDate instead:

gui.InputDate(gui.InputDateCfg{
    ID:          "due-date",
    IDFocus:     5,
    Date:        app.DueDate,
    Placeholder: "Pick a date",
    Sizing:      gui.FillFit,
})

DatePickerRoller provides a drum/slot-machine style date entry suited to touch interfaces:

gui.DatePickerRoller(gui.DatePickerRollerCfg{
    ID:           "roller",
    IDFocus:      6,
    SelectedDate: app.RollerDate,
    OnChange: func(date time.Time, w *gui.Window) {
        gui.State[App](w).RollerDate = date
    },
})

ColorPicker

gui.ColorPicker(gui.ColorPickerCfg{...}) provides RGBA color selection. An optional HSV view can be toggled at runtime.

gui.ColorPicker(gui.ColorPickerCfg{
    ID:      "fill-color",
    Color:   app.SelectedColor,
    ShowHSV: app.ShowHSV,
    OnColorChange: func(color gui.Color, _ *gui.Event, w *gui.Window) {
        gui.State[App](w).SelectedColor = color
    },
})

ThemePicker

gui.ThemePicker(gui.ThemePickerCfg{...}) is a specialised selector for switching between registered themes at runtime. The showcase uses it in the top-right corner.

gui.ThemePicker(gui.ThemePickerCfg{
    ID:          "app-theme",
    IDFocus:     7,
    FloatAnchor: gui.FloatTopRight,
    FloatTieOff: gui.FloatBottomRight,
    OnSelect: func(name string, _ *gui.Event, w *gui.Window) {
        if theme, ok := gui.ThemeGet(name); ok {
            gui.SetTheme(theme)
        }
    },
})

See Theming for how themes are defined and registered.


InputDate

gui.InputDate(gui.InputDateCfg{...}) combines a text field for date entry with an attached dropdown calendar. Accepts direct keyboard input (parsed per the current locale's date format) or selection from the DatePicker.

gui.InputDate(gui.InputDateCfg{
    ID:           "birth-date",
    IDFocus:      20,
    Date:         app.BirthDate,
    OnSelect: func(dates []time.Time, _ *gui.Event, w *gui.Window) {
        if len(dates) > 0 {
            gui.State[App](w).BirthDate = dates[0]
        }
    },
})

Constraints (AllowedWeekdays, AllowedMonths, AllowedYears, AllowedDates) carry through to the embedded DatePicker.


MathSpinner

gui.MathSpinner(gui.MathSpinnerCfg{...}) renders an animated spinner based on a parametric mathematical curve — epitrochoids, roses, Lissajous curves, lemniscates, and spirograph-like hypotrochoids. 16 built-in curve types are available via CurveType.

gui.MathSpinner(gui.MathSpinnerCfg{
    Width:     64,
    Height:    64,
    Curve:     gui.CurveRose,
    Color:     gui.CurrentTheme().ColorSelect,
    Thickness: 3,
})

The CurveType constants: CurveOriginalThinking (epitrochoid, k=7), CurveThinkingFive (k=5), CurveThinkingNine (k=9), CurveRoseOrbit, CurveRose through CurveRoseFour, CurveLissajous, CurveLemniscate, CurveHypotrochoid, and CurveThreePetalSpiral through CurveSixPetalSpiral. Override ParamA, ParamB, and ParamD to customise the generating curve parameters.

Clone this wiki locally