Views
A component builds its UI when it mounts. Use ui.Show and ui.For when children should appear, disappear, or reorder as state changes.
#How views work
Every component returns *ui.Element. Pass children with .Child(...) or .Children(...). Return ui.Fragment(...) for several siblings without a wrapper.
func ViewExample() *ui.Element {
return ui.View().Padding(20).Gap(12).Children(
ui.Text("Hello from Go"),
ui.Button().Child("Continue").OnClick(func() {}),
)
}A plain Go if or for runs only while the component is being built. It will not update later.
#Conditional content
Use ui.Show to mount or remove children from state.
func DisclosureExample() *ui.Element {
open, setOpen := ui.CreateSignal(false)
return ui.View().Children(
ui.Button().Child("Toggle details").OnClick(func() { setOpen(!open()) }),
ui.Show(
open,
func() *ui.Element { return ui.Text("Details") },
),
)
}#Lists
Use ui.For for a list that can change. Give each row a stable, unique key — a database ID, not its index. ui.KeyedFor also gives the row an accessor to the current item.
type ListPerson struct {
ID int
Name string
}
func KeyedListExample() *ui.Element {
people, setPeople := ui.CreateSignal([]ListPerson{{1, "Ada"}, {2, "Grace"}})
return ui.View().Children(
ui.Button().Child("Reorder and rename").OnClick(func() {
setPeople([]ListPerson{{2, "Grace"}, {1, "Ada Lovelace"}})
}),
ui.KeyedFor(
people,
func(person ListPerson) any { return person.ID },
func(person func() ListPerson, index func() int) *ui.Element {
return ui.Text(
index(),
": ",
person().Name,
)
},
func() *ui.Element { return ui.Text("No people") },
),
)
}Pass a new slice when you edit data. Mutating the stored slice in place does not notify subscribers. For long lists, use VirtualList or Table.
#Window lifecycle
Each window has its own component root. Closing the window disposes its UI and effects. Register cleanup with ui.OnCleanup. ui.Async runs work off the UI goroutine, delivers the result back, and cancels if the component is gone.
func LoadingPanel(load func(context.Context) (string, error)) *ui.Element {
result, setResult := ui.CreateSignal("Loading…")
ui.Async(
load,
func(value string, err error) {
if err != nil {
setResult(err.Error())
return
}
setResult(value)
},
)
return ui.Text(result())
}#Current window
Capture native.CurrentWindow() while the component is mounting, then use that handle in callbacks.
func CloseButton() *ui.Element {
window := native.CurrentWindow()
return ui.Button().Child("Close window").OnClick(func() { window.Close() })
}#Testing
Run quickgui test from the app module. quickgui fmt --check checks formatting. The app is a Go executable, so the usual Go debugger and stack traces use your source files.
