-
Notifications
You must be signed in to change notification settings - Fork 1
Widgets Selection
Selection widgets let users choose one or more values from a fixed set. They all follow
the same callback pattern: OnClick or OnSelect receives the new value through the
window, state is mutated directly, and the view function reads it on the next frame.
gui.Toggle(gui.ToggleCfg{...}) is a latching button — it stays visually pressed when
Selected is true.
gui.Toggle(gui.ToggleCfg{
ID: "bold",
IDFocus: 1,
Label: "Bold",
Selected: app.Bold,
OnClick: func(_ *gui.Layout, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Bold = !gui.State[App](w).Bold
},
})gui.Checkbox(gui.ToggleCfg{...}) uses the same config struct as Toggle but renders as a
traditional labelled checkbox.
gui.Checkbox(gui.ToggleCfg{
ID: "agree",
IDFocus: 2,
Label: "I agree to the terms",
Selected: app.Agreed,
OnClick: func(_ *gui.Layout, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Agreed = !gui.State[App](w).Agreed
},
})gui.Switch(gui.SwitchCfg{...}) renders as an iOS-style on/off toggle.
gui.Switch(gui.SwitchCfg{
ID: "notifications",
IDFocus: 3,
Label: "Enable notifications",
Selected: app.Notifications,
OnClick: func(_ *gui.Layout, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Notifications = !gui.State[App](w).Notifications
},
})gui.Radio(gui.RadioCfg{...}) is a single radio button. Typically you use several in a
column with a shared GroupID so only one can be selected at a time.
for _, opt := range []struct{ label, value string }{
{"Small", "sm"},
{"Medium", "md"},
{"Large", "lg"},
} {
gui.Radio(gui.RadioCfg{
ID: "size-" + opt.value,
IDFocus: 10,
GroupID: "size-group",
Label: opt.label,
Selected: app.Size == opt.value,
Value: opt.value,
OnSelect: func(value string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Size = value
},
})
}gui.RadioButtonGroup(gui.RadioButtonGroupCfg{...}) wraps this pattern into a single
widget when you want horizontal button-style radio controls.
gui.Select(gui.SelectCfg{...}) is a dropdown that supports single and multi-selection.
It has built-in typeahead filtering.
// Single select
gui.Select(gui.SelectCfg{
ID: "language",
Placeholder: "Pick a language",
Selected: app.Language,
Options: []string{"Go", "Rust", "Zig", "C", "Python"},
OnSelect: func(sel []string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Language = sel
},
})
// Multi-select — just add SelectMultiple: true
gui.Select(gui.SelectCfg{
ID: "tags",
Placeholder: "Pick tags",
Selected: app.Tags,
SelectMultiple: true,
Options: []string{"backend", "frontend", "mobile", "data"},
OnSelect: func(sel []string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).Tags = sel
},
})Selected is []string in both cases. For single-select, the slice has at most one
element.
gui.Combobox(gui.ComboboxCfg{...}) combines a text input with a dropdown list. The user
can type to filter options or enter a value not in the list.
gui.Combobox(gui.ComboboxCfg{
ID: "city",
IDFocus: 5,
Text: app.City,
Options: []string{"New York", "London", "Tokyo", "Sydney"},
OnSelect: func(value string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).City = value
},
})gui.ListBox(gui.ListBoxCfg{...}) renders a scrollable list with optional multi-select
and drag-to-reorder. Items are typed ListBoxItem values carrying an ID, label, and
optional icon.
gui.ListBox(gui.ListBoxCfg{
ID: "files",
IDFocus: 6,
IDScroll: 100,
Sizing: gui.FillFit,
MaxHeight: 300,
Data: app.Files, // []ListBoxItem
Reorderable: true,
OnSelect: func(selected []string, _ *gui.Event, w *gui.Window) {
gui.State[App](w).SelectedFiles = selected
},
OnReorder: func(movedID, beforeID string, w *gui.Window) {
a := gui.State[App](w)
from, to := gui.ReorderIndices(itemIDs(a.Files), movedID, beforeID)
if from >= 0 {
sliceMove(&a.Files, from, to)
}
},
})IDScroll marks the list as a scrollable container so the framework tracks its scroll
position. See Focus and Scrolling for details.
Getting Started
Widgets
Layout & Interaction
Visuals
Reference