Skip to content

Data Widgets

List

Selectable list of items with optional headers, spacers, prefixes, and scrollbar.

PropTypeDescription
itemsimpl Iterator<Item = ListItem>List items
selectedusizeSelected index
scroll_keysboolEnable keyboard scroll keys
scroll_wheelboolEnable mouse wheel
scrollbarboolShow scrollbar
scrollbar_configScrollbarConfigFull scrollbar configuration (variant, gap, thumb, thumb styles)
show_scroll_indicatorsboolShow top/bottom overflow indicators
scroll_indicator_styleStyleOverflow indicator style
borderboolDraw border
titleStringBorder title
paddingimpl Into<Padding>Inner padding
empty_textStringText when list is empty
empty_text_styleStyleEmpty text style
active_styleStyleStyle for rows where ListItem::active(true)
active_symbolOption<impl Into<Arc<str>>>Prefix symbol for active rows
active_symbol_positionListSymbolPositionRender active symbol on the left or immediately after the label
active_symbol_styleStyleStyle for active symbol
selection_symbolOption<String>Prefix for selected item (e.g. "> ")
selection_styleStyleSelected item style
selection_full_widthboolExtend selection to full width
item_horizontal_paddingimpl Into<Padding>Left/right padding for normal rows (top/bottom ignored)
header_horizontal_paddingimpl Into<Padding>Left/right padding for header rows (top/bottom ignored)
focusableboolAccept focus
widthLengthWidth
heightLengthHeight
on_selectCallback<ListEvent>Selection changed
on_item_clickCallback<ListEvent>Row clicked with mouse
on_activateCallback<ListEvent>Item activated (Enter/double-click)
on_scroll_toCallback<usize>Scroll position changed

ListItem Types

rust
ListItem::new("Normal item")          // Selectable row
ListItem::header("Section Title")      // Non-selectable header row
ListItem::spacer()                     // Non-selectable blank row
ListItem::new("Service").active(true)  // Marks row as active
ListItem::role(ListItemRole::Header)   // Explicit role

// Multi-line rows
ListItem::new("build")
    .line(ListItemLine::new("target/debug/build.log").selection_left(false))

// Prefix helpers
ListItem::new("Item").numbered(1)
ListItem::new("Bullet").bulleted('•')
ListItem::new("Label")
    .prefix("> ")
    .prefix_style(Style::new().fg(Color::Cyan))

// Symbol can be rendered on a non-primary line (useful for "description above")
ListItem::new("description")
    .line(ListItemLine::new("label"))
    .symbol_line(1)

Keyboard/mouse selection and activation skip non-selectable rows (Header/Spacer).

ListItem::line(...) adds extra visual lines under the primary line. Selection, activation, and callbacks still use the item index (not visual line index).

ListItem::prefix(...) renders a prefix before the primary label and automatically indents extra lines to match the label start. Use .extra_line_indent(...) to override that alignment when needed.

selection_symbol (e.g. "> ") is prepended to the selected item. Unselected items are padded with spaces to maintain alignment. Include a trailing space in the symbol if needed.

Active row rendering is independent from selection. Use active_symbol_position(ListSymbolPosition::Right) to render the active marker after the label instead of in the left symbol column. When using the right position, include any desired separator in the symbol itself (for example " ✓").

item_horizontal_padding and header_horizontal_padding accept Padding, but only left/right are applied in List.

Pointer vs keyboard row hover: For List and Table, when item_hover_style is non-empty, changing selected from the keyboard or from component logic (not a row click) stops using the mouse position for per-row hover until the pointer moves. Widget-level hover and row clicks behave as usual. Tree uses an inner List with the same item_hover_style prop, so it follows the same rules automatically.

rust
List::new()
    .items(self.files.iter().map(|f| ListItem::new(f.name.clone())))
    .selected(self.selected)
    .scrollbar(true)
    .selection_symbol(Some("> ".to_string()))
    .selection_style(Style::new().fg(Color::Cyan).bold())
    .on_select(ctx.link().callback(|e| Msg::FileSelected(e.index)))
    .on_activate(ctx.link().callback(|e| Msg::FileOpened(e.index)))

Table

Structured data with rows, columns, and optional scrollbar.

PropTypeDescription
headerTableRowColumn header row
rowsVec<TableRow>Data rows
widthsVec<ColumnWidth>Column widths
selectedOption<usize>Selected row index
column_spacingu16Space between columns
scroll_keysboolKeyboard scroll
scroll_wheelboolMouse wheel
scrollbarboolScrollbar
scrollbar_configScrollbarConfigFull scrollbar configuration (variant, gap, thumb, thumb styles)
show_scroll_indicatorsboolOverflow indicators
scroll_indicator_styleStyleIndicator style
selection_symbolOption<String>Selected row prefix
selection_styleStyleSelected row style
header_styleStyleHeader row style
row_styleStyleDefault row style
alternating_row_styleStyleStyle applied to odd rows for zebra striping
row_style_full_widthboolExtend row hover/selection/zebra style across full row width
focusableboolAccept focus
widthLengthWidth
heightLengthHeight
on_selectCallback<TableEvent>Row selection changed
on_activateCallback<TableEvent>Row activated
on_scroll_toCallback<usize>Scroll position

Column Widths

rust
ColumnWidth::Fixed(10)   // Fixed cell width
ColumnWidth::Fill(1)     // Proportional fill
ColumnWidth::Min(5)      // Minimum width, fills remaining

Row Sizing

rust
TableRow::new(vec!["col1", "col2"])
    .height(2)           // Fixed height
    .auto_height()       // Height = max line count of cells
    .bottom_margin(1)    // Spacing below row

Heatmap Cells

rust
TableCell::heat_fg(value, &gradient, GradientRange::new(0.0, 100.0))  // Color fg by value
TableCell::heat_bg(value, &gradient, GradientRange::new(0.0, 100.0))  // Color bg by value

Inspector Patterns

rust
Table::inspector(true)   // Enable inspector presets

// Row helpers
TableRow::key_value("Name", "Alice")
TableRow::section("Personal Info")
TableRow::separator()

// Hierarchy
TableRow::new(cells)
    .depth(2)
    .disclosure(TableDisclosureState::Expanded)

Inspector styling hooks: inspector_key_style, inspector_value_style, inspector_section_style, inspector_separator_style, inspector_indent_size, inspector_disclosure_symbols, inspector_separator_char.

Row semantics: TableRowRole::{Normal, Section, Separator}.

rust
Table::new()
    .header(TableRow::new(vec!["ID", "Name", "Status"]))
    .rows(self.data.iter().map(|d| {
        TableRow::new(vec![d.id.to_string(), d.name.clone(), d.status.clone()])
    }).collect())
    .widths(vec![ColumnWidth::Fixed(5), ColumnWidth::Fill(1), ColumnWidth::Fixed(10)])
    .alternating_row_style(Style::new().bg(Color::indexed(236)))
    .row_style_full_width(true)
    .selected(Some(self.selected))
    .selection_style(Style::new().fg(Color::Cyan))
    .on_select(ctx.link().callback(|e| Msg::RowSelected(e.index)))

Tree

Hierarchical tree view with expand/collapse.

PropTypeDescription
rootTreeNodeConstructor - root node
gapu16Vertical gap between items
icon_gapu16Gap between icon and label
show_iconsboolShow expand/collapse icons
expanded_iconStringIcon for expanded nodes
collapsed_iconStringIcon for collapsed nodes
leaf_iconStringIcon for leaf nodes
icon_styleStyleIcon style
indent_styleStyleIndent guide style
indent_guide_styleStyleVertical indent guide
indent_gradientColorGradientGradient for indent depth
styleStyleBase style
hover_styleStyleHover style
item_hover_styleStyleIndividual item hover
selection_styleStyleSelected item style
selection_symbolStringSelected item prefix
selection_symbol_styleStylePrefix style
scrollbarboolScrollbar
scrollbar_configScrollbarConfigFull scrollbar configuration (variant, gap, thumb, thumb styles)
scroll_keysboolKeyboard scroll
scroll_wheelboolMouse wheel
empty_textStringText when tree is empty
empty_text_styleStyleEmpty text style
focusableboolAccept focus
activate_on_clickboolSingle-click activates
keymapTreeKeymapKeyboard expand/collapse mapping
focus_policyFocusPolicyAccordion behavior
widthLengthWidth
heightLengthHeight
on_selectCallback<TreeEvent>Node selected
on_toggleCallback<TreeToggleEvent>Node expanded/collapsed

Tree is implemented with an inner List (flattened visible rows). Per-row item_hover_style and pointer vs keyboard row hover behavior match List - see the callout under List.

Building Nodes

rust
TreeNode::new("parent")
    .expanded(true)
    .child(
        TreeNode::new("child-1")
    )
    .child(
        TreeNode::new("child-2")
            .child(TreeNode::new("grandchild"))
    )

// With styled ListItem
TreeNode::new(ListItem::from_spans(vec![
    Span::new("file.rs").fg(Color::Cyan),
    Span::new(" [modified]").fg(Color::Yellow),
]))

Events

rust
// TreeEvent { index: usize, path: Vec<usize> }
// TreeToggleEvent { index: usize, path: Vec<usize>, expanded: bool }

.on_select(ctx.link().callback(|e: TreeEvent| Msg::NodeSelected(e.path)))
.on_toggle(ctx.link().callback(|e: TreeToggleEvent| Msg::NodeToggled(e.path, e.expanded)))

Keymap: TreeKeymap supports expand/collapse via Left/Right, h/l, Space (toggle).


FileTree

Lazy-loading filesystem explorer built on Tree.

PropTypeDescription
rootimpl Into<String>Constructor - root directory path
show_hiddenboolShow hidden files (. prefix)
max_entries_per_dirusizeCap entries per directory
git_statusboolShow git status badges (default: true)
git_refresh_tokenu64Token to trigger deterministic git refresh
directory_iconStringDirectory icon
file_iconStringFile icon
symlink_iconStringSymlink icon
other_iconStringOther entry icon
explorerboolShow fuzzy search input
explorer_placeholderStringSearch input placeholder
explorer_prefixStringSearch input prefix
explorer_input_borderboolSearch input border
explorer_match_styleStyleFuzzy match highlight
explorer_dividerboolShow divider between search and tree
on_selectCallback<FileTreeEvent>File/dir selected
on_toggleCallback<FileTreeToggleEvent>Directory expanded/collapsed

Plus all Tree styling/scrolling props, including scrollbar_config.

Behavior:

  • Directories load on demand in a background command on first expand.
  • Fuzzy matching respects .gitignore/.ignore rules.
  • Auto-expands ancestor directories to reveal search matches.
  • Restores pre-search expansion state when query clears.
  • Queries containing file extensions (e.g. layout.rs) prioritize filename matches.
rust
FileTree::new("/home/user/projects")
    .git_status(true)
    .show_hidden(false)
    .explorer(true)
    .explorer_placeholder("Filter files...")
    .on_select(ctx.link().callback(|e: FileTreeEvent| Msg::FileSelected(e.path)))

Events

rust
// FileTreeEvent { path: PathBuf, kind: FileTreeEntryKind }
// FileTreeToggleEvent { path: PathBuf, kind: FileTreeEntryKind, expanded: bool }

LogView

High-throughput log list with level highlighting and fuzzy filtering.

PropTypeDescription
bufferArc<LogBuffer>Bounded ring buffer of log entries
filter_modeMatchModeFuzzy, Substring, Exact
case_sensitiveboolCase-sensitive filtering
auto_followboolAuto-scroll to newest entry
pausedboolPause log streaming display
trace_styleStyleTRACE level style
debug_styleStyleDEBUG level style
info_styleStyleINFO level style
warn_styleStyleWARN level style
error_styleStyleERROR level style
on_selectCallback<LogViewEvent>Entry selected
on_activateCallback<LogViewEvent>Entry activated

Plus standard list/scroll styling props, including scrollbar_config.

rust
let buffer = Arc::new(LogBuffer::new(10_000)); // 10k entry ring buffer

// In a background thread: buffer.push(LogEntry { level, message });

LogView::new(buffer.clone())
    .filter_mode(MatchMode::Fuzzy)
    .auto_follow(true)
    .info_style(Style::new().fg(Color::Green))
    .error_style(Style::new().fg(Color::Red).bold())

Events

rust
// LogViewEvent { visible_index: usize, source_index: usize, entry: LogEntry }

MIT OR Apache-2.0