lv-tui
A reactive TUI framework for Rust. Component tree, reactive state, CSS-like styling, event bubbling, focus management — everything you need to build complex terminal applications.
use *;
use Component;
Features
- Component tree — compose UIs with Column, Row, Stack, Block, Scroll, Overlay
- Reactive state —
#[reactive(paint)]auto-triggers repaint on change - Declarative events —
#[event_handlers]macro withon_focus,on_blur,on_tick,on_key_*naming convention - Event bubbling — Capture → Target → Bubble with
stop_propagation() - Focus management — Tab/Shift+Tab navigation with Focus/Blur events
- CSS-like stylesheets — type/class/id selectors with pseudo-classes (
:focus,:hover,:disabled,:focus-within) and style inheritance - 24-bit color —
Color::Rgb(r,g,b),Color::Indexed(i),Color::hex("#ff8800"), plus"text".rgb(255,0,0)via Stylize - Unicode — CJK/Emoji wide characters, text wrap, truncation, alignment
- Timer API —
cx.set_timer(ms),cx.set_interval(ms),cx.cancel_timer(id)for one-shot and periodic dispatch - Cancellable workers —
cx.spawn_worker()returnsWorkerIdfor tracking and cancellation - Headless testing —
Pilotdriver with event injection, buffer inspection,press(),run_until() - Debug view — press
dto visualize component borders and labels
Widgets
| Widget | Description |
|---|---|
Label |
Text display with styling |
Input |
Single-line text input with cursor |
TextArea |
Multi-line editor with undo/redo, line numbers, word navigation |
Column |
Vertical layout container |
Row |
Horizontal layout container |
Stack |
Layered/z-order container |
Block |
Border + padding wrapper with optional title |
Scroll |
Scrollable content container |
Overlay |
Modal dialog with background dimming |
Table |
Data table with headers, row/cell selection, fixed rows, sorting |
Tabs |
Tabbed container with keyboard navigation |
Select |
Dropdown with keyboard navigation |
Checkbox |
Toggleable boolean with label |
RadioGroup |
Mutually exclusive radio selection |
ProgressBar |
Unicode 8-segment progress bar |
Dialog |
Border + key bindings (Esc/Enter) wrapper |
SplitPane |
Resizable split panels (Ctrl+arrows) |
VirtualList |
Virtual-scrolling list for large datasets |
Spinner |
Animated loading indicator |
DiffView |
Unified diff display for text comparisons |
Tree |
Hierarchical tree with expand/collapse, guide lines |
MarkdownView |
Markdown renderer (in lv-tui-markdown crate) |
Text System
All widgets accept impl Into<Text>, giving you three levels of control:
use *;
// Simple: plain text
new
// Styled: use Stylize trait — named colors, 24-bit, or hex
new
new
// Multi-line: build Text from Lines
new
Declarative Events
Replace manual fn event() with #[event_handlers]:
Handlers follow naming convention: on_focus, on_blur, on_tick, on_key_<char> (e.g. on_key_q), on_key_<name> (e.g. on_key_tab, on_key_enter, on_key_space).
24-bit Color
use *;
// Construct colors
let c = Rgb;
let c = hex.unwrap;
let c = Indexed; // 256-color palette
// Stylize chainable methods
let span = "hello".rgb.bold;
let span = "world".hex.underline;
let span = "text".on_rgb.white;
CSS Pseudo-classes
}
}
}
use ;
let sheet = parse.unwrap;
let state = WidgetState ;
let style = sheet.resolve;
Timer API
Testing
use Pilot;
let mut pilot = new;
pilot.focus_first;
pilot.press.unwrap; // inject key
pilot.press.unwrap;
// Assert rendered output
assert!;
// Run until condition
let done = pilot.run_until.unwrap;
Getting Started
[]
= "0.3"
License
MIT