Documentation
¶
Overview ¶
Package list provides a cursor-driven, optionally filterable list inside a bordered pane. It bundles item storage, cursor tracking, viewport auto- scroll, and a filter.Model together so parents can drop it in with one New + Update + View.
Items are plain []string — callers format their data before passing it in. For filtering, the match is a case-insensitive substring across the item text. Anything richer (fuzzy match, per-field search, struct items) is out of scope and should be composed via pane + filter directly.
Index ¶
- type ActivatedMsg
- type KeyedItem
- type Keys
- type Model
- func (m *Model) Blur()
- func (m *Model) BlurFilter()
- func (m *Model) ClearMarks()
- func (m Model) Cursor() int
- func (m *Model) Deselect()
- func (m Model) Filtering() bool
- func (m *Model) Focus() tea.Cmd
- func (m *Model) FocusFilter() tea.Cmd
- func (m Model) FocusToken() focus.Token
- func (m Model) Focused() bool
- func (m Model) Help() []key.Binding
- func (m Model) Init() tea.Cmd
- func (m Model) IsActivate(msg tea.Msg) bool
- func (m Model) IsCapturingKeys() bool
- func (m Model) Items() []string
- func (m Model) Loading() bool
- func (m Model) MarkCount() int
- func (m Model) Markable() bool
- func (m Model) Marks() []string
- func (m Model) Rect() geom.Rect
- func (m Model) Selected() (string, bool)
- func (m Model) SelectedIndex() (int, bool)
- func (m Model) SelectedKey() (string, bool)
- func (m Model) Selection() []string
- func (m Model) SelectionLabel() string
- func (m *Model) SetActiveColor(c lipgloss.TerminalColor)
- func (m *Model) SetCursor(n int)
- func (m *Model) SetInactiveColor(c lipgloss.TerminalColor)
- func (m *Model) SetItems(items []string)
- func (m *Model) SetKeyedItems(items []KeyedItem)
- func (m *Model) SetLoading(b bool) tea.Cmd
- func (m *Model) SetLoadingLabel(s string)
- func (m *Model) SetMarks(keys []string)
- func (m *Model) SetRect(r geom.Rect)
- func (m *Model) SetSelectedColor(c lipgloss.TerminalColor)
- func (m *Model) SetSpinnerStyle(s lipgloss.Style)
- func (m *Model) SetTitle(s string)
- func (m *Model) SetTopRight(s string)
- func (m *Model) SetValue(s string)
- func (m *Model) ToggleMark()
- func (m *Model) ToggleMarkAll()
- func (m Model) Update(msg tea.Msg) (Model, tea.Cmd)
- func (m Model) Value() string
- func (m Model) View() string
- func (m Model) Visible() []string
- type Options
- type SelectedChangedMsg
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActivatedMsg ¶ added in v0.18.0
ActivatedMsg is emitted when the user opens the selected item with a double click — the mouse spelling of enter (rule 14). Index and Item match the selection at the moment of the second click.
Token identifies which list sent it, so a screen holding several lists can tell them apart. Prefer IsActivate over matching this type directly unless you need the payload.
type KeyedItem ¶
KeyedItem is a list entry with a stable identity. Pass to SetKeyedItems to preserve the cursor across data swaps even when items are reordered or partially replaced — e.g. polled refreshes of a live data set.
type Keys ¶
type Keys struct {
Up, Down key.Binding
Top, Bottom key.Binding
HalfUp, HalfDown key.Binding
Filter key.Binding
Mark, MarkAll key.Binding
Pane pane.Keys
}
Keys is the list's keymap. Each binding carries both its dispatch keys (WithKeys) and its help label (WithHelp) — Update and Help() read from the same struct, so a custom binding propagates everywhere. The embedded pane.Keys covers horizontal scroll; mutate fields on Pane to override h-scroll without touching the rest.
func DefaultKeys ¶
func DefaultKeys() Keys
DefaultKeys returns the list's stock keymap. Mutate the returned value to override individual actions.
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the list widget. Embed as a value; mutate via the setters.
func (*Model) Blur ¶ added in v0.18.0
func (m *Model) Blur()
Blur releases the keyboard, clearing *both* regions. Leaving a filter focused on a blurred component is what lets a second filterable pane end up invisibly eating keys.
func (*Model) BlurFilter ¶ added in v0.18.1
func (m *Model) BlurFilter()
BlurFilter returns input from the filter to the body.
func (*Model) ClearMarks ¶ added in v0.21.0
func (m *Model) ClearMarks()
ClearMarks drops every mark.
func (*Model) Deselect ¶ added in v0.18.1
func (m *Model) Deselect()
Deselect moves the cursor off every row, so nothing is highlighted and Selected reports ok=false. Use it for a list that must start with no choice made — a form select that demands a deliberate pick.
SetCursor deliberately does not accept -1: it clamps, so a stray negative index cannot silently blank a list. Deselecting is a distinct intent and gets a distinct call.
func (Model) Filtering ¶
Filtering reports whether the embedded filter currently has focus — callers use this to decide whether to intercept global keys like "q".
func (*Model) Focus ¶ added in v0.18.0
Focus gives the component the keyboard, highlighting the body pane.
A filterable list has two focusable regions behind one Focusable, so this deliberately does nothing when the filter already owns input: a click on the filter also asks the group for focus, and the grant arrives afterwards. Without this guard that grant would snatch the highlight back to the body while the filter kept the keystrokes.
func (*Model) FocusFilter ¶ added in v0.18.1
FocusFilter moves input to the filter and takes the highlight off the body, so exactly one region ever reads as active.
func (Model) FocusToken ¶ added in v0.18.0
FocusToken returns the list's stable focus identity. See focus.Identified.
func (Model) Focused ¶ added in v0.18.0
Focused reports whether either of the component's regions owns input.
func (Model) Help ¶
Help returns the keys this list responds to. While the embedded filter is focused it returns the filter's keys; otherwise the configured nav/scroll/filter bindings from m.keys.
func (Model) IsActivate ¶ added in v0.18.0
IsActivate reports whether msg means "open this list's selection" — enter from the keyboard while the filter isn't taking input, or this list's own double-click activation.
Rule 14 makes those the same verb, and routing them through one predicate is what keeps them that way: a screen writes the open branch once and both inputs reach it.
if s.menu.IsActivate(msg) {
return s, screen.Push(detailFor(s.menu.Cursor()))
}
func (Model) IsCapturingKeys ¶ added in v0.18.0
IsCapturingKeys reports whether the list currently swallows printable keys — true while its filter is focused. Satisfies focus.Capturer, so a focus.Group can answer the app shell's global-key gating (rule 5) without the screen restating it.
func (Model) MarkCount ¶ added in v0.21.0
MarkCount is how many keys are marked, including any whose rows the current filter hides.
func (Model) Marks ¶ added in v0.21.0
Marks returns the marked keys in item order — not in the order they were marked, so the result is stable across equivalent selections.
func (Model) Rect ¶ added in v0.21.0
Rect is the area the list occupies, for a caller that needs to test a position against it before acting — deciding whether a right-click landed on this list, say. Matches the accessor input, toggle, form and confirm already expose.
func (Model) Selected ¶
Selected returns the currently highlighted item. ok is false when the visible set (post-filter) is empty.
func (Model) SelectedIndex ¶
SelectedIndex returns the highlighted row's index into the original (pre-filter) Items() slice. ok is false when the visible set is empty.
Use this when list items are formatted display strings rendered from a richer source slice — SelectedIndex identifies which source row is selected, regardless of whether a filter is currently applied. For the row's text, use Selected; for the cursor's position within the filtered view, use Cursor.
func (Model) SelectedKey ¶
SelectedKey returns the Key of the currently highlighted item when the list was populated via SetKeyedItems. ok is false when the visible set is empty or when items are anonymous (no keys set).
func (Model) Selection ¶ added in v0.21.0
Selection is the marked keys, or the cursor row's key when nothing is marked. Empty when the items are anonymous.
This is the accessor a screen should reach for, and the reason it exists is the branch it removes. Without it every caller writes
if ks := l.Marks(); len(ks) > 0 { … } else { … }
which is easy to write once and easy to forget, and whose failure mode is a verb quietly acting on one row when the user had marked six.
func (Model) SelectionLabel ¶ added in v0.21.0
SelectionLabel names the selection for a confirm string or a menu title: the single key, or "N items".
It returns the key rather than the display text because the key is the identity — display text is usually a formatted row with columns in it, which reads badly in a sentence. A caller wanting something else formats Selection() itself.
func (*Model) SetActiveColor ¶
func (m *Model) SetActiveColor(c lipgloss.TerminalColor)
SetActiveColor updates the body pane's active border color. Useful when reacting to a theme swap without rebuilding the model.
func (*Model) SetCursor ¶
SetCursor moves the cursor (clamped to the visible range) and scrolls to keep it on screen.
func (*Model) SetInactiveColor ¶
func (m *Model) SetInactiveColor(c lipgloss.TerminalColor)
SetInactiveColor updates the body pane's inactive border color.
func (*Model) SetItems ¶
SetItems replaces the item set, re-applies the current filter, and redraws. Clears any per-item keys previously set via SetKeyedItems.
func (*Model) SetKeyedItems ¶
SetKeyedItems replaces the item set with keyed entries and snaps the cursor to the previously-selected Key after the swap (falling back to the clamped previous cursor index when the key is gone). Use this for polled refreshes of a live data set so the user's selection survives reordering or partial replacement.
func (*Model) SetLoading ¶
SetLoading toggles the loading state. When entering, returns the spinner's initial Tick command — propagate it back from your screen's Update so the spinner animates. The list's Update already forwards every msg to the body pane, so subsequent ticks chain automatically.
func (*Model) SetLoadingLabel ¶
SetLoadingLabel updates the text rendered next to the spinner while loading.
func (*Model) SetMarks ¶ added in v0.21.0
SetMarks replaces the marked set. Keys that match no item are kept: an item set swapped out and back should not silently lose the user's selection. Carries marks across a SetTheme rebuild (rule 4).
func (*Model) SetRect ¶ added in v0.18.0
SetRect places the list in the given rect. When filterable, the internal filter pane consumes the top 3 rows and the body pane gets the rest, offset below it; otherwise the body pane takes the whole rect. Each child receives its own absolute rect so a click resolves to the right one.
func (*Model) SetSelectedColor ¶
func (m *Model) SetSelectedColor(c lipgloss.TerminalColor)
SetSelectedColor updates the foreground color of the highlighted row.
func (*Model) SetSpinnerStyle ¶
SetSpinnerStyle updates the lipgloss style applied to the spinner glyph.
func (*Model) SetTopRight ¶ added in v0.18.1
SetTitle updates the title rendered on the body pane's top border. Useful when the list represents a slice that can change identity at runtime (e.g. "detail · <selection>"). SetTopRight writes into the pane's top-right border slot. Hosts use it for a short annotation that belongs to the component as a whole — pkg/form paints validation errors there. Pass "" to clear.
func (*Model) SetValue ¶
SetValue overwrites the filter text (no-op when not filterable). Useful when rebuilding the list on theme swap / resize — carry the old Value().
func (*Model) ToggleMark ¶ added in v0.21.0
func (m *Model) ToggleMark()
ToggleMark flips the mark on the cursor row. No-op when marking is off or the items are anonymous.
func (*Model) ToggleMarkAll ¶ added in v0.21.0
func (m *Model) ToggleMarkAll()
ToggleMarkAll marks every currently visible row, or clears them when they are all already marked.
Visible means post-filter, which is the useful reading: filter to a subset, mark it wholesale, act. Under a windowed table the same rule applies to the rows actually held — see table.ToggleMarkAll.
func (Model) Update ¶
Update consumes up/down/j/k and "/" (when filterable); while the filter is focused, every key is forwarded to it. Mouse events inside the list's rect move the cursor and request focus. Non-key messages are forwarded to the body pane so spinner ticks reach the loading-state animation.
type Options ¶
type Options struct {
Width, Height int
// Title sits on the pane's top-left border slot. Defaults to "List".
Title string
// Items is the full item set. The list copies this slice so the caller
// can mutate their source independently.
Items []string
// Filterable embeds a filter.Model above the body pane (three rows). If
// false, "/" is ignored and the full height is used for items.
Filterable bool
// Pane pass-throughs. See pkg/pane.Options for defaults.
ActiveColor lipgloss.TerminalColor
InactiveColor lipgloss.TerminalColor
ActiveBorder lipgloss.Border
InactiveBorder lipgloss.Border
SlotBrackets pane.SlotBracketStyle
// HScrollbar reserves a row at the bottom of the list pane for a
// horizontal scrollbar and lets ←/h and →/l scroll long rows
// horizontally. theme.List() enables this by default — disable when
// items are guaranteed short and the extra row is unwanted.
HScrollbar bool
// SelectedColor foregrounds the highlighted row (bold).
SelectedColor lipgloss.TerminalColor
// Markable adds a mark column and binds space / ctrl+a, so the user can
// build a multi-selection the screen reads back with Selection().
//
// Off by default, and it costs a row nothing when off: the gutter stays
// two cells wide. Marking requires keyed items (SetKeyedItems) — see
// mark.go for why holding marks by index is not an option.
Markable bool
// MarkStyle colors the ✓ on a marked row that isn't under the cursor.
// The cursor row is drawn as one styled run instead, so its highlight
// cannot be broken mid-row (rule 19).
MarkStyle lipgloss.Style
// SpinnerStyle is applied to the spinner glyph rendered while the list
// is in its loading state (see SetLoading). Pass via theme.List() for
// a sensible default.
SpinnerStyle lipgloss.Style
// LoadingLabel is rendered next to the spinner while loading — e.g.
// "loading cities…".
LoadingLabel string
// Filter configures the embedded filter. Ignored when Filterable=false.
Filter filter.Options
// Keys is the list's keymap. Leave zero to use DefaultKeys; set
// individual bindings to override (others fall back to defaults via
// fillDefaults). theme.List() pre-populates this.
Keys Keys
}
Options configures a new list. Zero-value fields fall back to sane defaults where that's meaningful; otherwise the pane/filter defaults apply.
type SelectedChangedMsg ¶ added in v0.17.0
type SelectedChangedMsg struct {
// Index is the cursor's position in the post-filter visible slice.
// Zero when Empty is true.
Index int
// Item is the currently focused item's string value. Empty when
// Empty is true.
Item string
// Empty is true when no item is focused (empty visible set or
// cursor out of range). Index / Item are zero-valued.
Empty bool
}
SelectedChangedMsg is emitted by the list when the cursor lands on a different item than the last time we emitted — after cursor movement, after a SetItems / filter operation that changes which item is under the cursor, or on the initial view. Parents subscribe to it to drive "detail on hover" patterns: refetch a parameterized detail source keyed on the focused item. Dedup is on (index, item) so a SetItems swap that lands the same content under the cursor doesn't re-emit; a swap that changes the content does. Empty=true fires only as a transition (had focus → no focus) — an initially-empty list never emits.