ListWidget
A selectable list of text items with keyboard and mouse navigation.
Lists are interactive, focusable widgets that allow users to navigate through items and select or activate them. They're ideal for menus, file browsers, todo lists, and any UI requiring item selection.
Basic Usage
Create a list using the fluent API with an array of strings:
dotnet runNavigation
Use Up/Down arrows to move between items. The selected item is highlighted when the list has focus. Press Tab to move focus to other widgets.
Selection Changed Events
The OnSelectionChanged event fires whenever the user navigates to a different item:
dotnet runThe ListSelectionChangedEventArgs provides:
SelectedIndex- The index of the newly selected itemSelectedText- The text of the newly selected itemWidget- The source ListWidgetNode- The underlying ListNodeContext- Access to the application context
Selection vs Activation
OnSelectionChanged fires when navigating with arrow keys. Use OnItemActivated (shown below) to respond to Enter/Space/Click actions.
Item Activated Events
The OnItemActivated event fires when the user activates an item with Enter, Space, or mouse click:
dotnet runThe ListItemActivatedEventArgs provides:
ActivatedIndex- The index of the activated itemActivatedText- The text of the activated itemWidget- The source ListWidgetNode- The underlying ListNodeContext- Access to the application context
Common Pattern
Use OnItemActivated for actions like toggling checkboxes, opening details, or navigating to a new screen. Use OnSelectionChanged for updating dependent UI like preview panes.
Event Handlers
Both OnSelectionChanged and OnItemActivated accept synchronous and asynchronous handlers:
Synchronous Handler
v.List(items).OnItemActivated(e => {
Console.WriteLine($"Activated: {e.ActivatedText}");
})2
3
Asynchronous Handler
v.List(items).OnItemActivated(async e => {
await SaveSelectionAsync(e.ActivatedIndex);
})2
3
Render Loop Blocking
Async handlers block the render loop while awaiting. For long operations, use the background work pattern shown in the ButtonWidget documentation.
Keyboard Navigation
Lists support comprehensive keyboard navigation:
| Key | Action |
|---|---|
| Up Arrow | Move to previous item (wraps to last) |
| Down Arrow | Move to next item (wraps to first) |
| Enter | Activate current item |
| Space | Activate current item |
| Tab | Move focus to next widget |
| Shift+Tab | Move focus to previous widget |
Wrap-Around Navigation
When reaching the first item, pressing Up wraps to the last item. Similarly, pressing Down at the last item wraps to the first.
Mouse Support
Lists support mouse interaction in terminals that support mouse events:
- Left Click - Selects the clicked item (fires
OnSelectionChangedif selection changed) and then activates it (firesOnItemActivated) - Mouse Wheel Up - Moves selection to the previous item
- Mouse Wheel Down - Moves selection to the next item
Long Lists with Scrolling
When a list has more items than can fit in its container, it automatically becomes scrollable. The viewport scrolls to keep the selected item visible as you navigate:
dotnet runUse the .FixedHeight() extension to constrain the list to a specific number of rows. The list will:
- Show only the visible items within the viewport
- Automatically scroll when navigating beyond visible bounds
- Keep the selected item centered when possible
- Support both keyboard and mouse wheel scrolling
Performance
Long lists are efficient because only visible items are rendered. You can safely use lists with hundreds of items without performance concerns.
Focus Behavior
Lists visually indicate their focus and selection state:
| State | Appearance |
|---|---|
| Unfocused, item selected | > Item (indicator only) |
| Focused, item selected | > Item (highlighted with theme colors) |
| Unfocused, item not selected | Item (no indicator) |
When a list loses focus, the selected item still shows the selection indicator but without the highlighting. This helps users track which item was last selected.
Theming
Customize list appearance using theme elements:
var theme = Hex1bTheme.Create()
.Set(ListTheme.SelectedForegroundColor, Hex1bColor.Black)
.Set(ListTheme.SelectedBackgroundColor, Hex1bColor.Cyan)
.Set(ListTheme.SelectedIndicator, "▶ ")
.Set(ListTheme.UnselectedIndicator, " ");
await using var terminal = Hex1bTerminal.CreateBuilder()
.WithHex1bApp((app, options) =>
{
options.Theme = theme;
return ctx => /* ... */;
})
.Build();
await terminal.RunAsync();2
3
4
5
6
7
8
9
10
11
12
13
14
15
Available Theme Elements
| Element | Type | Default | Description |
|---|---|---|---|
ForegroundColor | Hex1bColor | Default | Text color for unselected items |
BackgroundColor | Hex1bColor | Default | Background for unselected items |
SelectedForegroundColor | Hex1bColor | White | Text color when focused and selected |
SelectedBackgroundColor | Hex1bColor | Blue | Background when focused and selected |
SelectedIndicator | string | "> " | Indicator for selected items |
UnselectedIndicator | string | " " | Indicator for unselected items |
Custom Indicators
Change the selection indicators to match your app's style. Common alternatives include "→ ", "● ", "▸ ", or emoji like "👉 ".
State Management
Lists preserve their selection state across reconciliation. The selected index is managed internally by the ListNode and persists even when the widget tree is rebuilt.
When the items list changes, the selection is automatically clamped to valid bounds:
- If the selected index is beyond the new list length, it moves to the last item
- If the list becomes empty, the selection resets to index 0
Related Widgets
- ButtonWidget - For single-action controls
- TextBoxWidget - For text input with selection
- ScrollWidget - For scrollable content areas
- VStackWidget - For vertical layout of widgets