Live Display¶
The Live component enables flicker-free, auto-updating terminal displays. Perfect for dashboards, real-time monitoring, and dynamic content.
Quick Example¶
use fast_rich::prelude::*;
use fast_rich::live::Live;
use std::thread;
use std::time::Duration;
fn main() {
let mut live = Live::new();
live.start().unwrap();
for i in 0..10 {
let text = Text::plain(format!("Counter: {}", i));
live.update(text);
live.refresh().unwrap();
thread::sleep(Duration::from_millis(500));
}
live.stop().unwrap();
}
How It Works¶
Live manages the terminal cursor to redraw content in place:
- Start: Saves cursor position, hides cursor
- Update: Stores new content to render
- Refresh: Clears previous output, draws new content
- Stop: Restores cursor, cleans up
This creates smooth, flicker-free updates without screen flashing.
Basic Usage¶
Creating and Starting¶
use fast_rich::live::Live;
let mut live = Live::new();
live.start().expect("Failed to start live display");
Updating Content¶
// Update with any Renderable
live.update(Text::plain("New content"));
live.update(table);
live.update(panel);
live.update(layout);
Refreshing Display¶
Stopping¶
Live Clock Example¶
use fast_rich::prelude::*;
use fast_rich::live::Live;
use std::thread;
use std::time::Duration;
use chrono::Local;
fn main() {
let mut live = Live::new();
live.start().unwrap();
for _ in 0..60 {
let time = Local::now().format("%H:%M:%S").to_string();
let panel = Panel::new(
Text::styled(
&format!("🕐 {}", time),
Style::new().bold().foreground(Color::Cyan)
)
).title("Live Clock");
live.update(panel);
live.refresh().unwrap();
thread::sleep(Duration::from_secs(1));
}
live.stop().unwrap();
}
Live Dashboard with Layout¶
Combine Live with Layout for complex dashboards:
use fast_rich::prelude::*;
use fast_rich::live::Live;
use fast_rich::layout::Layout;
fn main() {
let mut live = Live::new();
live.start().unwrap();
for tick in 0..100 {
// Create layout structure
let mut layout = Layout::new();
layout.split_row(vec![
Layout::new().with_name("left"),
Layout::new().with_name("right"),
]);
// Update content
let left_panel = Panel::new(Text::plain("Status: Active"));
let right_panel = Panel::new(Text::plain(format!("Tick: {}", tick)));
layout.children_mut()[0].update(left_panel);
layout.children_mut()[1].update(right_panel);
live.update(layout);
live.refresh().unwrap();
std::thread::sleep(std::time::Duration::from_millis(100));
}
live.stop().unwrap();
}
Error Handling¶
Always handle potential errors:
use fast_rich::live::Live;
fn run_dashboard() -> Result<(), Box<dyn std::error::Error>> {
let mut live = Live::new();
live.start()?;
// ... updates ...
live.stop()?;
Ok(())
}
Real Terminal Output¶
Live display in action
Code
use fast_rich::prelude::*;
use fast_rich::live::Live;
use std::thread;
use std::time::Duration;
fn main() {
let mut live = Live::new();
live.start().unwrap();
for i in 0..100 {
let panel = Panel::new(Text::plain(format!("Update: {}", i)))
.title("Live Display");
live.update(panel);
live.refresh().unwrap();
thread::sleep(Duration::from_millis(50));
}
live.stop().unwrap();
}
Run it
What you'll see

Tips¶
Update Frequency
Limit updates to ~10-30 FPS for smooth visual output without overwhelming the terminal:
Graceful Exit
Use Ctrl+C handling to ensure live.stop() is called:
Nested Live Displays
Don't start multiple Live instances. Use a single root Live
with Layout for complex UIs.
Print During Live
Avoid using println! or console.print() while Live is active.
All output should go through live.update().