tui_skeleton/lib.rs
1//! Animated skeleton loading widgets for [Ratatui](https://ratatui.rs).
2//!
3//! Placeholder widgets that pulse, sweep, or shimmer while data loads.
4//! All widgets are stateless — pass `elapsed_ms` from your event loop and the
5//! animation state is computed purely from the timestamp.
6//!
7//! Two orthogonal axes control appearance:
8//!
9//! - **Animation mode** ([`AnimationMode`]) — Breathe, Sweep, Plasma, or Noise
10//! - **Fill variant** (`.braille(bool)`) — solid `█` or braille `⣿`
11//!
12//! # Widgets
13//!
14//! - [`SkeletonBlock`] — Filled rectangle (atomic unit)
15//! - [`SkeletonTable`] — Rows with column separators, ragged cell widths, zebra striping
16//! - [`SkeletonList`] — Short spaced items with ragged edges (menu/sidebar)
17//! - [`SkeletonText`] — Paragraph simulation with varying line widths
18//! - [`SkeletonStreamingText`] — Typewriter-style chat text filling over time
19//! - [`SkeletonBarChart`] — Vertical bars of varying height
20//! - [`SkeletonHBarChart`] — Horizontal bars of varying length
21//! - [`SkeletonBrailleBar`] — Braille progress bars with rounded caps and peak marker
22//! - [`SkeletonKvTable`] — Key-value pairs (properties/detail panel)
23//! - [`SkeletonLineChart`] — Braille line chart with overlapping wave traces
24//!
25//! # Example
26//!
27//! ```rust
28//! use tui_skeleton::{SkeletonBlock, AnimationMode, Color};
29//!
30//! let elapsed_ms = 1000u64;
31//!
32//! // Solid fill with sweep animation
33//! let solid = SkeletonBlock::new(elapsed_ms)
34//! .mode(AnimationMode::Sweep)
35//! .base(Color::Rgb(30, 22, 58))
36//! .highlight(Color::Rgb(49, 40, 78));
37//!
38//! // Braille fill with breathe animation
39//! let braille = SkeletonBlock::new(elapsed_ms)
40//! .braille(true)
41//! .base(Color::Rgb(30, 22, 58))
42//! .highlight(Color::Rgb(49, 40, 78));
43//!
44//! // TV noise — random braille glyphs changing every frame
45//! let noise = SkeletonBlock::new(elapsed_ms)
46//! .mode(AnimationMode::Noise);
47//! ```
48//!
49//! # Adaptive Tick Rate
50//!
51//! Skeleton animations look best at ~20 FPS ([`TICK_ANIMATED`]) but most TUI
52//! applications tick at ~5 FPS ([`TICK_IDLE`]) for static content. The
53//! recommended pattern:
54//!
55//! 1. Track whether any skeleton widget is currently visible
56//! 2. Use [`TICK_ANIMATED`] when skeletons are on screen
57//! 3. Revert to [`TICK_IDLE`] when all data has loaded
58//!
59//! This keeps CPU usage low while delivering smooth animations during loading.
60
61pub(crate) mod animation;
62pub mod bar_chart;
63pub mod block;
64pub mod braille_bar;
65pub mod hbar_chart;
66pub mod kv_table;
67pub mod line_chart;
68pub mod list;
69pub mod streaming_text;
70pub mod table;
71pub mod text;
72
73#[cfg(feature = "pantry")]
74pub mod use_cases;
75
76pub use animation::AnimationMode;
77pub use bar_chart::SkeletonBarChart;
78pub use block::SkeletonBlock;
79pub use braille_bar::SkeletonBrailleBar;
80pub use hbar_chart::SkeletonHBarChart;
81pub use kv_table::SkeletonKvTable;
82pub use line_chart::SkeletonLineChart;
83pub use list::SkeletonList;
84pub use streaming_text::SkeletonStreamingText;
85pub use table::SkeletonTable;
86pub use text::SkeletonText;
87
88// Re-export types consumers need so they never depend on ratatui-core/ratatui-widgets directly.
89pub use ratatui_core::layout::Constraint;
90pub use ratatui_core::style::Color;
91pub use ratatui_widgets::block::Block;
92
93use std::time::Duration;
94
95/// Recommended tick interval when skeleton widgets are visible (50ms / 20 FPS).
96pub const TICK_ANIMATED: Duration = Duration::from_millis(50);
97
98/// Recommended tick interval for static content (200ms / 5 FPS).
99pub const TICK_IDLE: Duration = Duration::from_millis(200);
100
101/// Default colors that work on both dark and light terminals.
102pub mod defaults {
103 use ratatui_core::style::Color;
104
105 pub const BASE: Color = Color::DarkGray;
106 pub const HIGHLIGHT: Color = Color::Gray;
107}