Skip to content

Input Widgets

Button

Interactive button.

PropTypeDescription
labelimpl Into<String>Constructor - button text
variantButtonVariantVisual variant
styleStyleIdle style
hover_styleStyleHover style
focus_styleStyleFocus style
border_styleBorderStyleIdle border
hover_border_styleBorderStyleHover border
focus_border_styleBorderStyleFocus border
alignAlignLabel alignment
paddingimpl Into<Padding>Inner padding
iconSpanIcon span (prepended to label)
icon_styleStyleIcon style
icon_gapu16Space between icon and label
shortcutStringKeyboard shortcut label
shortcut_bindingsKeyBindingsKeyboard shortcut alternatives (displayed canonically)
shortcut_styleStyleShortcut style
shortcut_gapu16Space between label and shortcut
widthLengthWidth
heightLengthHeight
focusableboolWhether button accepts focus
disabledboolDisable button
disabled_styleStyleStyle when disabled
on_clickCallback<MouseEvent>Click / Enter callback
on_keyKeyHandlerKey handler
rust
Button::new("Save")
    .style(Style::new().fg(Color::White).bg(Color::Blue))
    .shortcut_bindings("ctrl+s, super+s".parse().unwrap())
    .focus_style(Style::new().fg(Color::White).bg(Color::DarkBlue).bold())
    .on_click(ctx.link().callback(|_| Msg::Save))

DragSource

Wrapper that turns a single child into a generic drag source.

PropTypeDescription
childimpl Into<Element>Wrapped draggable content
on_drag_startFn(DragStartEvent) -> Option<Box<dyn DragPayload>>Drag-start handler that returns payload; None aborts drag
on_drag_cancelCallback<DragCancelEvent>Fired when drag is canceled or dropped on invalid target
on_drag_startedCallback<DragStartedEvent>Fired once when the drag activates (after the movement threshold); includes payload
drag_groupimpl Into<Arc<str>>Optional compatibility group
clear_drag_group()Remove group restriction
previewDragPreviewLabel text near pointer, SourceSnapshot (layout slot collapses per drag_slot; float preview copies cells), or None
preview_labelimpl Into<Arc<str>>Convenience for DragPreview::Label
preview_snapshot()Convenience for DragPreview::SourceSnapshot
no_preview()Convenience for DragPreview::None
drag_slotDragSlotCollapse (0 main-axis cells) or Specified(Length) using the same Length rules as stack children (Auto, Px, Percent, Flex). In VStack/HStack the stack axis applies; elsewhere use drag_slot_axis.
drag_slot_collapse()Same as drag_slot(DragSlot::Collapse)
drag_slot_lengthLengthSame as drag_slot(DragSlot::Specified(len))
drag_slot_axisDragSlotAxisVertical or Horizontal: which axis Fixed/Collapse apply to when measured outside a stack (default: vertical)
dragging_styleStyleOverlay while dragging: first-frame tint, reserved slot fill when using SourceSnapshot, and label/none preview modes
preview_max_widthOption<u16>Max width of the floating SourceSnapshot preview (NoneDEFAULT_PREVIEW_MAX_WIDTH)
preview_max_heightOption<u16>Max height of the floating preview (NoneDEFAULT_PREVIEW_MAX_HEIGHT)
preview_max_size(Option<u16>, Option<u16>)Set both max dimensions
thresholdu16Pointer movement threshold before drag starts (default: 3)
enabledboolEnable/disable drag behavior
rust
DragSource::new()
    .child(Text::new("main.rs"))
    .on_drag_start(|ev| {
        let _ = (ev.x, ev.y);
        Some(Box::new(String::from("main.rs")) as Box<dyn DragPayload>)
    })
    .preview_label("main.rs")
    .threshold(3)

DropTarget

Wrapper that marks a single child as a generic drop zone.

PropTypeDescription
childimpl Into<Element>Wrapped drop-zone content
on_drag_overCallback<DragOverEvent>Fired when compatible payload hovers target
on_drag_leaveCallback<DragLeaveEvent>Fired when active drag leaves target
on_dropCallback<DropEvent>Fired on successful drop
accept_groupimpl Into<Arc<str>>Restrict accepted source group
clear_accept_group()Accept all groups (None)
can_acceptPayloadAcceptFnOptional payload predicate
can_accept_withFn(&dyn DragPayload) -> boolClosure form of payload predicate
clear_can_accept()Remove payload predicate
highlightDropHighlightNone, Fill, Placeholder (bordered frame), or Overlay (tint after children)
highlight_styleStyleStyle for Fill / Placeholder / Overlay
highlight_fillStylehighlight(DropHighlight::Fill) + highlight_style
highlight_placeholderStylehighlight(DropHighlight::Placeholder) + highlight_style
highlight_overlayStylehighlight(DropHighlight::Overlay) + highlight_style
drop_slotDropSlotChild (render child normally, default) or SourcePreview (replace child with the dragged card's snapshot; cursor float is suppressed)
drop_slot_source_preview()Shorthand for drop_slot(DropSlot::SourcePreview)
enabledboolEnable/disable drop behavior

on_drag_over is emitted on every pointer move while a compatible drag hovers this target (not only on enter). Use DragOverEvent::local_y (offset from the drop target’s top edge) with a row-height estimate to place a single insertion line. DropEvent::local_y uses the same convention.

rust
DropTarget::new()
    .child(Text::new("Drop here"))
    .accept_group("files")
    .can_accept_with(|payload| payload.downcast_ref::<String>().is_some())
    .on_drop(ctx.link().callback(|ev| Msg::Dropped(ev.payload)))

Clickable text link built on top of Button with link-style defaults.

PropTypeDescription
labelimpl Into<Arc<str>>Constructor - visible link text
hrefArc<str>Optional URL metadata emitted in callbacks
styleStyleIdle style
hover_styleStyleHover style
focus_styleStyleFocus style
disabled_styleStyleStyle when disabled
visited_styleStyleStyle overlay when visited: true
alignAlignLabel alignment
paddingimpl Into<Padding>Inner padding
widthLengthWidth
heightLengthHeight
focusableboolWhether link accepts focus
disabledboolDisable interaction
visitedboolMark link as visited
on_activateCallback<HyperlinkEvent>Emits on click, Enter, and Space
on_keyKeyHandlerFallback key handler
rust
Hyperlink::new("Open docs")
    .href("https://example.com/docs")
    .visited(self.docs_opened)
    .visited_style(Style::new().fg(Color::Magenta).underline())
    .on_activate(ctx.link().callback(Msg::OpenLink))

HyperlinkEvent contains:

  • label: Arc<str>
  • href: Option<Arc<str>>

Open the destination explicitly from component logic:

rust
if let Some(url) = ev.href.as_deref() {
    let _ = tui_lipan::utils::open_url(url);
}

Input

Single-line text input field.

PropTypeDescription
valueimpl Into<String>Constructor - current text value
cursorusizeByte cursor position
anchorOption<usize>Selection anchor (for text selection)
caret_shapeCaretShapeCursor shape - default: Block (only set when you want Bar or Underline)
caret_colorOption<Color>OSC 12 cursor color (terminal support required)
styleStyleIdle style
focus_styleStyleFocused style
placeholderStringPlaceholder when empty
maskOption<char>Masking character (e.g., '*' for passwords)
read_onlyboolAllow selection but block keyboard input
focusableboolWhether input accepts focus; mouse selection and Ctrl+C copy still work when false
widthLengthWidth
heightLengthHeight
on_changeCallback<String>Emits new value on each keystroke
on_editCallback<TextEditEvent>Emits structured edit events
key_interceptorKeyHandlerRuns before text insertion
rust
Input::new(self.query.clone())
    .placeholder("Search...")
    .style(Style::new().fg(Color::White))
    .focus_style(Style::new().fg(Color::White).bg(Color::indexed(237)))
    .on_change(ctx.link().callback(Msg::QueryChanged))

caret_color uses OSC 12. Set TUI_LIPAN_OSC12=0 to disable if your terminal doesn't support it.

Undo/Redo: Ctrl+Z, Ctrl+Shift+Z, Ctrl+Y (also handles raw control codes).


TextArea

Multi-line text editor.

PropTypeDescription
valueimpl Into<String>Constructor - current text value
cursorusizeByte cursor position
anchorOption<usize>Selection anchor
caret_shapeCaretShapeCursor shape - default: Block (only set when you want Bar or Underline)
caret_colorOption<Color>OSC 12 cursor color
line_numbersboolShow line number gutter
gutter_insetu16Empty cells before the gutter / line numbers
wrapboolWord wrap (default: true)
max_widthOption<u16>Max line width before forced wrap
scroll_offsetOption<usize>Controlled vertical scroll
scroll_wheelboolMouse wheel scrolling
scrollbarboolVertical scrollbar
scrollbar_configScrollbarConfigFull scrollbar configuration (variant, gap, thumb, thumb styles)
h_scrollbarboolHorizontal scrollbar (only when wrap: false)
styleStyleIdle style
focus_styleStyleFocused style
placeholderStringPlaceholder when empty
placeholder_styleStylePlaceholder style
focus_placeholder_styleStylePlaceholder when focused
read_onlyboolAllow selection but block keyboard input
triple_click_modeTripleClickSelectionModeTriple-click selects a line or paragraph
newline_bindingTextAreaNewlineBindingEnter key behavior
on_changeCallback<TextAreaEvent>Emits value, cursor, anchor on each edit
on_editCallback<TextEditEvent>Structured edit events
sentinelsVec<TextAreaSentinel>Custom inline PUA tokens (SENTINEL_BASE + index in value)
on_sentinels_changeCallback<Vec<TextAreaSentinel>>Fires when the list is pruned (e.g. user deleted a token)
on_sentinel_eventCallback<Vec<SentinelEvent>>Lifecycle events with stable ids (e.g. Deleted)
key_interceptorKeyHandlerRuns before text editing
on_scrollCallback<ScrollEvent>Scroll event with metrics
on_scroll_toCallback<usize>Target scroll offset
color_strategyBox<dyn TextAreaColorStrategy>Syntax highlighting strategy
languageStringLanguage hint for syntax highlighting; use language_from_path(path) to resolve from a file path
themeStringSyntax theme name
imagesVec<ImageContent>Attached images
on_images_changeCallback<Vec<ImageContent>>Images list updated
image_modeTextAreaImageModeInline or Attachment
image_placeholderStringPlaceholder text for inline images
image_placeholder_styleStyleInline image placeholder style
on_image_pasteCallback<ImageContent>Legacy: image pasted via Ctrl+V
widthLengthWidth
heightLengthHeight
focusableboolParticipate in focus traversal; mouse selection and Ctrl+C copy still work when false
rust
TextArea::new(self.text.clone())
    .line_numbers(true)
    .wrap(false)
    .h_scrollbar(true)
    .on_change(ctx.link().callback(Msg::TextChanged))

Custom inline sentinels (extmarks)

Styled atomic tokens in the buffer use a separate PUA range from inline images: SENTINEL_BASE (U+F000). Entry i in sentinels maps to the single character U+F000 + i in value. One backspace/delete removes the whole codepoint; the framework prunes the parallel sentinels list and can emit SentinelEvent batches (see docs/enums.md and docs/events.md).

Type / APIRole
TextAreaSentinelLabel, styles, optional type-erased payload, optional SentinelId (or assign via insert_sentinel)
insert_sentinel(value, cursor, sentinels, sentinel)Insert at cursor; assigns SentinelId::next() when id is unset
TextAreaSnapshotcapture / apply / diff for in-memory stash–restore

Prefer on_sentinel_event for cleanup keyed by stable id; keep on_sentinels_change if you only need the pruned list.

Example: examples/text_area_sentinels.rs

Syntax Highlighting (requires feature syntax-syntect)

rust
TextArea::new(code.clone())
    .with_syntax("rust", "base16-ocean.dark")

// With background colors
    .with_syntax_bg("rust", "one-dark")

// Auto-detect language from file path (extension/filename matching, no I/O)
TextArea::new(code.clone())
    .language_from_path("src/main.rs")   // resolves to "Rust"
    .with_syntax_strategy(SyntectStrategy::default(), "Rust", "base16-ocean.dark")

// Or use the free function to get the language string yourself
if let Some(lang) = tui_lipan::language_from_path(&file_path) {
    area = area.language(lang);
}

// Custom theme from file
    .with_syntax_custom_theme_from_file("rust", "MyTheme", "/path/to/theme.tmTheme")

Built-in themes: Catppuccin Frappe, Catppuccin Latte, Catppuccin Macchiato, Catppuccin Mocha, Dracula, InspiredGitHub, Monokai Extended, One Dark (Atom), Solarized (dark), Solarized (light), base16-eighties.dark, base16-mocha.dark, base16-ocean.dark, base16-ocean.light.

SyntectStrategy::use_background(true) - apply syntax theme backgrounds (default: false).

When a TextArea, DocumentView, or DiffView uses SyntectStrategy, the app theme can now gently recolor token categories via Theme::syntax(...) while still using the selected syntect theme for tokenization and base styling.

Image Modes (requires feature image)

Inline mode (images embedded as Unicode PUA sentinels in text value):

rust
TextArea::new(self.input.clone())
    .image_mode(TextAreaImageMode::Inline)
    .images(self.images.clone())
    .on_images_change(ctx.link().callback(Msg::ImagesChanged))
    .image_placeholder("[Img]")
    .image_placeholder_style(Style::new().fg(Color::Magenta).bold())

Sentinel characters (U+E000…) represent images in the text value. Cursor movement and deletion work naturally. Use IMAGE_SENTINEL_BASE to construct sentinel chars manually if needed.

Attachment mode (images in separate list, text value unchanged):

rust
VStack::new()
    .gap(0)
    .child(
        if !self.images.is_empty() {
            DraggableTabBar::new()
                .tabs(self.images.iter().enumerate().map(|(i, _)| {
                    DraggableTab::new(format!("Image {}", i + 1)).closeable(true)
                }))
                .active(usize::MAX)
                .close_symbol("x")
                .draggable(false)
                .focusable(false)
                .on_close(ctx.link().callback(Msg::RemoveImage))
                .into()
        } else { Element::empty() }
    )
    .child(
        TextArea::new(self.input.clone())
            .image_mode(TextAreaImageMode::Attachment)
            .images(self.images.clone())
            .on_images_change(ctx.link().callback(Msg::ImagesChanged))
    )

Image pasting is opt-in: only active when on_images_change or on_image_paste is set. Without these, Ctrl+V pastes text only.


DiffView (requires feature diff-view)

Diff viewer with pluggable backends:

  • DiffViewBackend::TextArea (default) - supports editable mode
  • DiffViewBackend::DocumentView - read-only review + selection optimized

Backend selection rules:

  • Explicit .backend(...) always wins.
  • If backend is not set explicitly, calling .document_view(...) switches to DocumentView.
  • If backend is not set explicitly, calling .text_area(...) switches to TextArea.
  • Outer DiffView sizing inherits the active backend's width/height unless you override it with .width(...) / .height(...).
  • Pane borders are rendered by internal Frame wrappers, not by inner TextArea/DocumentView borders.

Line numbers in DiffView are source-mapped (git-style), not visual-row counters:

  • Split left pane shows original (before) line numbers.
  • Split right pane shows modified (after) line numbers.
  • Unified mode uses original numbers for removed lines, and modified numbers for added/context lines.
PropTypeDescription
beforeStringConstructor (first arg) - original text
afterStringConstructor (second arg) - modified text
modeDiffViewModeSplit (default) or Unified
backendDiffViewBackendTextArea (default) or DocumentView
editableboolEnable editing (TextArea backend only)
widthLengthOverride outer diff view width (otherwise inherit active backend width)
heightLengthOverride outer diff view height (otherwise inherit active backend height)
wrapboolApply wrapping to both backends
line_numbersboolToggle line numbers in both backends
min_line_number_widthu8Minimum gutter digits in both backends
gutter_insetu16Empty cells before the gutter / line numbers in both backends
borderboolToggle outer border around the whole DiffView
panels_borderboolToggle per-pane wrapper borders
scrollbarboolToggle vertical scrollbar in both backends
h_scrollbarboolToggle horizontal scrollbar in both backends
focusableboolToggle focusability in both backends
single_scrollbarboolIn split mode, show vertical scrollbar only on right pane
join_frameboolJoin split-pane wrapper frames (Frame::join_frame)
vertical_separatorboolInsert vertical divider between split panes
vertical_separator_charcharCharacter used by split divider
vertical_separator_styleStyleStyle for split divider
highlight_full_widthboolExtend changed-line background highlight to full row width
word_diffboolWord-level diff highlighting
trim_common_indentboolTrim the smallest shared leading indent from visible diff lines (default: true)
show_prefixesboolShow +/- prefix symbols
diff_styleDiffPaletteAdded/removed/context-separator/patch-header styles
neutral_bgColorConvenience setter for context/unchanged line background
base_color_strategyBox<dyn TextAreaColorStrategy>Syntax highlighting base strategy
languageStringLanguage hint; use language_from_path(path) to resolve from a file path
themeStringSyntax theme name
text_areaTextAreaPre-configured TextArea for scroll/border/wrap settings
document_viewDocumentViewPre-configured DocumentView for scroll/border/wrap settings
scroll_offsetusizeControlled scroll offset (applies to rendered pane(s))
context_linesusizeCollapse unchanged regions farther than n lines from any change into a separator line (default: show all)
show_context_separatorboolShow/hide the context separator placeholder when collapsing context (default: true)
context_separator_textStringTemplate for context separator text; supports {count}, {line_word}, {direction}, {arrow}
shared_selection_idArc<str>Cross-widget selection group id (unified: as-is; split: auto-suffixed :left/:right)
on_scrollCallback<DiffScrollEvent>Pane-aware scroll callback (pane + ScrollEvent)
rust
let diff = DiffView::new(before, after)
    .mode(DiffViewMode::Split)
    .document_view(DocumentView::new("")) // backend inferred
    .height(Length::Auto) // useful for inline/message-style diff blocks
    .border(true)
    .panels_border(true)
    .wrap(true)
    .line_numbers(true)
    .min_line_number_width(4)
    .single_scrollbar(true)
    .join_frame(true)
    .vertical_separator(true)
    .vertical_separator_style(Style::new().dim())
    .highlight_full_width(true)
    .neutral_bg(Color::rgb(24, 24, 24))
    .word_diff(true)
    .show_prefixes(true);

By default, `DiffView` derives its added/removed/marker styling from `Theme::diff`.
Use `.diff_style(...)` only when you want per-widget overrides.

`DiffView` also trims shared leading indentation by default so deeply indented code is easier to read inline. Use `.trim_common_indent(false)` when you need the original left margin preserved exactly.

// Efficient: build DiffData once, reuse across renders
let data = DiffData::with_config(before, after, config);
let diff = DiffView::new(before, after).with_diff(data);
// or: DiffView::new(before, after).with_shared_diff(Arc<DiffData>)

// DiffDataConfig fields:
// - word_diff: bool        - precompute word-level diff tokens
// - context_lines: Option<usize> - collapse unchanged regions (same as the prop)
// - show_context_separator: bool   - insert separator placeholder (default: true)
// - context_separator_text: Arc<str> - template for separator text

// Split scroll sync pattern (controlled):
let mut offset: Option<usize> = None;
let mut diff = DiffView::new(before, after)
    .mode(DiffViewMode::Split)
    .on_scroll(ctx.link().callback(|ev: DiffScrollEvent| Msg::DiffScrolled(ev)));
if let Some(v) = offset {
    diff = diff.scroll_offset(v);
}

// Custom diff colors (lines + markers + line numbers):
let style = DiffPalette {
    added: Style::new().bg(Color::rgb(0x14, 0x2F, 0x20)),
    removed: Style::new().bg(Color::rgb(0x3B, 0x1E, 0x24)),
    context_line_number: Style::new().fg(Color::DarkGray), // fg/bg for unchanged line numbers in gutter
    added_marker: Style::new().fg(Color::Green),
    removed_marker: Style::new().fg(Color::Red),
    added_line_number: Style::new().fg(Color::DarkGray),   // fg/bg for added line numbers in gutter
    removed_line_number: Style::new().fg(Color::DarkGray), // fg/bg for removed line numbers in gutter
    context_separator_style: Style::new().fg(Color::DarkGray).dim(), // style for context-collapse separator lines
    patch_header: Style::new().fg(Color::Cyan).bold(), // style for in-band `diff --git ...` metadata lines
    ..DiffPalette::default()
};

// Context lines - collapse unchanged regions far from changes:
DiffView::new(before, after)
    .context_lines(3) // show 3 lines of context around each change
    .context_separator_text("{arrow} {count} {line_word} omitted {direction}")
    .show_context_separator(false) // omit separator placeholders entirely
    .mode(DiffViewMode::Unified);
// Separator lines are excluded from copy operations.
// Both Split and Unified modes support context_lines.
// Default separator text is arrow-based and direction-aware, e.g. "↑ 9 hidden lines above ↑".
// The separator style is themed by default (dimmed muted text); override via DiffPalette::context_separator_style.
// Raw patch metadata lines like `diff --git a/... b/...` stay in the scrollable diff and use DiffPalette::patch_header.

// Auto-detect language from file path (requires feature `syntax-syntect`):
DiffView::new(before, after)
    .language_from_path("src/main.rs")  // resolves to "Rust", no-op if unknown
    .theme("One Dark (Atom)");          // set theme separately; with_syntax() would override the detected language

Checkbox

Toggle widget for boolean values.

PropTypeDescription
checkedboolConstructor - checked state
stateCheckboxStateFull state (overrides checked)
indeterminateboolShow indeterminate state
labelStringLabel text
variantCheckboxVariantVisual variant
gapu16Space between box and label
styleStyleIdle style
hover_styleStyleHover style
focus_styleStyleFocus style
checked_styleStyleStyle when checked
unchecked_styleStyleStyle when unchecked
indeterminate_styleStyleStyle when indeterminate
label_styleStyleLabel style
paddingimpl Into<Padding>Padding
disabledboolDisable interaction
disabled_styleStyleStyle when disabled
on_toggleCallback<bool>Toggle callback
on_clickCallback<()>Click callback

Radio

Radio button group.

PropTypeDescription
optionsVec<Arc<str>>Constructor - option labels
selectedOption<usize>Selected index
layoutRadioLayoutVertical or Horizontal
variantRadioVariantVisual variant
gapu16Space between options
styleStyleBase style
checked_styleStyleSelected item style
unchecked_styleStyleUnselected item style
hover_styleStyleHover style
focus_styleStyleFocus style
label_styleStyleLabel style
disabledboolDisable interaction
disabled_styleStyleStyle when disabled
on_changeCallback<usize>Selection changed callback
rust
Radio::new(vec!["Option A".into(), "Option B".into(), "Option C".into()])
    .selected(Some(self.choice))
    .layout(RadioLayout::Horizontal)
    .on_change(ctx.link().callback(Msg::ChoiceChanged))

Select

Dropdown select widget.

PropTypeDescription
optionsVec<String>Available options
selectedOption<usize>Selected index
placeholderStringPlaceholder when nothing selected
expandedboolControlled expanded state
widthLengthWidth
disabledboolDisable interaction
on_selectCallback<usize>Item selected
on_changeCallback<usize>Selection changed
on_toggleCallback<bool>Dropdown opened/closed
button_variantButtonVariantTrigger button variant
button_styleStyleButton idle style
button_hover_styleStyleButton hover style
button_focus_styleStyleButton focus style
button_disabled_styleStyleButton disabled style
button_border_styleBorderStyleTrigger border style (outlined variant)
button_hover_border_styleBorderStyleTrigger border style when hovered
button_focus_border_styleBorderStyleTrigger border style when focused
button_open_suffixStringTrigger suffix while expanded
button_closed_suffixStringTrigger suffix while collapsed
button_suffix_styleStyleTrigger suffix style
list_titleStringDropdown title (bordered list)
list_title_styleStyleDropdown title style
list_borderboolDropdown list border
list_border_styleBorderStyleDropdown border style
list_paddingimpl Into<Padding>Dropdown padding
list_styleStyleDropdown list style
list_selection_styleStyleSelected item style
list_selection_full_widthboolExtend selection style across full row
list_selection_symbolOption<String>Selection symbol for selected row
list_selection_symbol_styleStyleSelection symbol style
list_hover_styleStyleHover style in list
list_widthLengthDropdown width override
list_heightLengthDropdown height override
match_button_widthboolForce dropdown width to trigger width
list_scrollbarboolScrollbar in list
list_scrollbar_configScrollbarConfigFull scrollbar configuration (variant, gap, thumb, thumb styles)
list_empty_textStringDropdown empty text
list_empty_text_styleStyleDropdown empty text style
list_disabled_styleStyleDropdown disabled style

ComboBox

Controlled input + dropdown list for searchable selection.

PropTypeDescription
itemsVec<Arc<str>>Source options
queryArc<str>Controlled input value
placeholderStringInput placeholder
openboolControlled dropdown state
active_indexOption<usize>Active source index
selectedOption<usize>Selected source index fallback
allow_custom_valueboolAllow Enter to commit free-form query
widthLengthInput width
list_widthLengthDropdown width override
list_heightLengthDropdown height
match_input_widthboolForce dropdown width to match input width
disabledboolDisable interaction
input_hover_styleStyleInput hover style
input_disabled_styleStyleInput disabled style
input_hover_border_styleBorderStyleInput border style while hovered
input_open_suffixStringSuffix when dropdown is open
input_closed_suffixStringSuffix when dropdown is closed
input_suffix_styleStyleInput suffix style
input_focus_suffix_styleStyleInput suffix style when focused
on_query_changeCallback<Arc<str>>Input query changed
on_open_changeCallback<bool>Request open/close change
on_active_index_changeCallback<Option<usize>>Active source index changed
on_commitCallback<ComboBoxCommitEvent>Enter/activate commit event

ComboBoxCommitEvent contains:

  • index: Option<usize>
  • value: Arc<str>
  • from_custom_value: bool

Interaction notes:

  • With match_input_width(true), dropdown width follows the rendered trigger/input width.

MultiSelect

Controlled list for selecting multiple items with Space toggle and Enter commit.

PropTypeDescription
itemsimpl Iterator<Item = impl Into<MultiSelectItem>>Source rows
active_indexusizeActive source index
selected_indicesVec<usize>Controlled selected source indices
max_selectedusizeOptional maximum selected rows
selected_prefixStringPrefix for selected rows (default: [x])
unselected_prefixStringPrefix for unselected rows (default: [ ])
description_styleStyleStyle used for item descriptions
description_placementMultiSelectDescriptionPlacementDescription placement: Inline, Right, Above, Below
description_overflowMultiSelectDescriptionOverflowDescription overflow policy: Truncate or Wrap (Wrap applies to Above/Below)
description_selectionboolWhether selection highlight applies to descriptions
widthLengthWidth
heightLengthHeight
titleStringList title (requires border)
title_styleStyleList title style
selection_full_widthboolExpand selection style across row width
disabledboolDisable interaction
disabled_styleStyleStyle when disabled
empty_textStringText when list is empty
empty_text_styleStyleEmpty-text style
on_active_index_changeCallback<usize>Active row changed
on_toggleCallback<MultiSelectToggleEvent>Current row toggled
on_changeCallback<MultiSelectChangeEvent>Selected set changed
on_commitCallback<MultiSelectCommitEvent>Enter commit with selected set

Event payloads:

  • MultiSelectToggleEvent { index, selected }
  • MultiSelectChangeEvent { selected_indices }
  • MultiSelectCommitEvent { selected_indices }

Interaction notes:

  • Space toggles the active_index row.
  • Mouse click on a row toggles that row and updates the active row.
  • Enter emits on_commit (mouse click does not commit).

MultiSelectItem supports optional descriptions:

rust
MultiSelectItem::new("Cargo.toml")
    .description("Workspace manifest")

description_selection(false) only affects Above/Below description lines. For Inline and Right, selection/hover styling still applies to the full row.

description_overflow(MultiSelectDescriptionOverflow::Wrap) affects only Above/Below placement. Inline and Right keep single-row truncation behavior.


HexArea

Hex/ASCII binary data viewer with keyboard cursor navigation.

PropTypeDescription
bytesArc<[u8]>Constructor - byte buffer to render
cursorusizeControlled cursor byte index
anchorOption<usize>Optional selection anchor byte index
read_onlyboolRead-only mode flag
bytes_per_rowu16Number of bytes rendered per row
show_asciiboolShow ASCII preview column
show_offsetsboolShow hexadecimal offset gutter
uppercase_hexboolUppercase (AA) or lowercase (aa) hex output
scroll_offsetOption<usize>Controlled row scroll offset
styleStyleBase style
hover_styleStyleHover style
focus_styleStyleFocus style
selection_styleStyleSelection style
cursor_styleStyleCursor byte style
pending_edit_styleStyleBackground/style for half-entered nibble edits
borderboolDraw border
border_styleBorderStyleBorder style
paddingimpl Into<Padding>Inner padding
widthLengthWidth
heightLengthHeight
focusableboolParticipate in focus traversal
disabledboolDisable interaction
on_cursor_changeCallback<HexAreaCursorEvent>Emits on cursor movement (keyboard/mouse)
on_changeCallback<HexAreaChangeEvent>Emits updated bytes after edits
on_editCallback<HexAreaEditEvent>Emits per-edit metadata (replace/insert/delete)
on_scrollCallback<ScrollEvent>Emits desired row offset during navigation/wheel scrolling
on_keyKeyHandlerCustom key handler fallback

HexAreaCursorEvent contains:

  • cursor: usize
  • anchor: Option<usize>

Interaction notes:

  • Hex and ASCII columns are both clickable and map to the same byte index.
  • Click-and-drag creates/extends a byte-range selection.
  • First typed hex digit clears the cell to <digit> and enters pending-nibble mode.
  • Pending-nibble mode highlights the edited cell with pending_edit_style.
  • Esc cancels pending-nibble mode and restores the original byte.

HexAreaEditEvent contains:

  • index: usize
  • before: Option<u8>
  • after: Option<u8>
  • kind: HexAreaEditKind

Edit keys (when read_only(false) and on_change is set):

  • Hex digits (0-9, a-f) replace bytes in two-keystroke nibble mode
  • Insert inserts 0x00 at cursor
  • Delete removes byte at cursor
  • Backspace removes byte before cursor
  • Ctrl+Z undo, Ctrl+Shift+Z/Ctrl+Y redo

Slider

Numeric selection slider.

PropTypeDescription
valuef64Constructor - current value
minf64Minimum value
maxf64Maximum value
stepf64Step increment
labelStringLabel text
show_valueboolShow current value
thumb_symbolcharThumb character
track_symbolcharEmpty track character
filled_track_symbolcharFilled track character
hover_thumb_symbolcharThumb on hover
styleStyleBase style
filled_track_styleStyleFilled portion style
filled_track_gradientColorGradientFilled portion gradient
thumb_styleStyleThumb style
thumb_gradientColorGradientThumb gradient
focus_styleStyleFocus style
focus_thumb_styleStyleThumb when focused
hover_thumb_styleStyleThumb on hover
label_styleStyleLabel style
paddingimpl Into<Padding>Padding
widthLengthWidth
heightLengthHeight
focusableboolAccept focus
on_changeCallback<f64>Value changed
on_clickCallback<f64>Click / Enter

DatePicker

Calendar-based date selection.

PropTypeDescription
yeari32Current year
monthu32Current month (1–12)
dayOption<u32>Selected day
titleStringCalendar title
show_outside_daysboolShow days from adjacent months
borderboolDraw border
border_styleBorderStyleBorder appearance
paddingimpl Into<Padding>Padding
styleStyleBase style
header_styleStyleMonth/year header style
weekday_styleStyleWeekday name row style
day_styleStyleRegular day style
day_hover_styleStyleDay hover style
selected_styleStyleSelected day style
outside_month_styleStyleAdjacent-month day style
nav_styleStyleNavigation button style
nav_hover_styleStyleNavigation button hover
nav_disabled_styleStyleDisabled navigation style
widthLengthWidth
heightLengthHeight
on_selectCallback<(i32, u32, u32)>Day selected (year, month, day)
on_prev_monthCallback<()>Previous month navigation
on_next_monthCallback<()>Next month navigation

MIT OR Apache-2.0