Focus and Input
Focus Manager
Track focus across named components:
go
focus := tui.NewFocusManager("sidebar", "content", "input")
focus.Next() // advance to next
focus.Prev() // go to previous
focus.Focus("input") // focus by name
focus.IsFocused("sidebar") // check current
focus.Current() // get current name
focus.Index() // get current indexTab-Based Focus Switching
go
func (a *app) Update(msg tui.Msg) (tui.Component, tui.Cmd) {
switch msg := msg.(type) {
case tui.KeyMsg:
if msg.Type == tui.KeyTab {
a.focus.Next()
return a, nil
}
if msg.Type == tui.KeyBacktab {
a.focus.Prev()
return a, nil
}
}
// Delegate to focused component
switch a.focus.Current() {
case "sidebar":
a.list, _ = a.list.Update(msg)
case "content":
a.viewport, _ = a.viewport.Update(msg)
case "input":
a.input, _ = a.input.Update(msg)
}
return a, nil
}Visual Focus Indication
Use the theme system to style focused borders:
go
func (a *app) Render(buf *tui.Buffer, area tui.Rect) {
block := a.theme.Block("Sidebar", a.focus.IsFocused("sidebar"))
a.list.SetBlock(block)
a.list.Render(buf, area)
}Form Widget
The Form widget has built-in focus management across fields:
go
form := widget.NewForm(
widget.NewFormField("Name", "Enter name"),
widget.NewFormField("Email", "user@example.com"),
widget.NewFormField("Password", ""),
)
// Tab/Down moves to next field, Shift+Tab/Up moves to previous
form, _ = form.Update(msg)
// Read values
name := form.Value("Name")
all := form.Values() // map[string]string