# ratatui-toolkit
[](https://crates.io/crates/ratatui-toolkit)
[](https://docs.rs/ratatui-toolkit)
[](LICENSE-MIT)

A comprehensive collection of reusable TUI components for [ratatui](https://ratatui.rs/), the Rust terminal UI library.
## Features
| **ResizableSplit** | Draggable split panels (vertical/horizontal) with mouse support |
| **TreeView** | Generic tree widget with expand/collapse, navigation, and selection |
| **FileSystemTree** | File browser with devicons and sorting |
| **MarkdownRenderer** | Render markdown to styled ratatui `Text` |
| **Toast** | Toast notifications with auto-expiry and severity levels |
| **Dialog** | Modal dialogs (Info/Success/Warning/Error/Confirm) |
| **Button** | Clickable buttons with hover states |
| **HotkeyFooter** | Keyboard shortcut display footer |
| **MenuBar** | Horizontal menu bar with icons |
| **StatusLineStacked** | Neovim-style powerline status |
| **TermTui** | Terminal emulator with mprocs-style copy mode |
## Installation
Add to your `Cargo.toml`:
```toml
[dependencies]
ratatui-toolkit = "0.1"
```
Or with specific features:
```toml
[dependencies]
ratatui-toolkit = { version = "0.1", default-features = false, features = ["tree", "split", "toast"] }
```
## Feature Flags
| `markdown` | ✅ | Markdown rendering to ratatui Text |
| `tree` | ✅ | Generic tree view widget |
| `dialog` | ✅ | Modal dialog components |
| `toast` | ✅ | Toast notification system |
| `split` | ✅ | Resizable split panels |
| `menu` | ✅ | Menu bar component |
| `statusline` | ✅ | Powerline-style statusline |
| `terminal` | ✅ | Terminal emulator (TermTui) |
| `file-tree` | ❌ | File system tree with devicons |
| `full` | ❌ | Enable all features |
## Quick Start
```rust
use ratatui::prelude::*;
use ratatui_toolkit::prelude::*;
// Create a resizable split
let split = ResizableSplit::new(SplitDirection::Vertical)
.ratio(0.3)
.min_ratio(0.1)
.max_ratio(0.9);
// Create a toast notification
let toast = Toast::new("File saved successfully!")
.level(ToastLevel::Success)
.duration(Duration::from_secs(3));
// Render markdown
let text = render_markdown("# Hello\n\nThis is **bold** and *italic*", None);
```
## Examples
Run examples with:
```bash
cargo run --example resizable_split_demo
cargo run --example tree_view_demo --features tree
cargo run --example toast_manager_demo --features toast
cargo run --example markdown_demo --features markdown
cargo run --example full_app_demo --features full
```
### Resizable Split
```rust
use ratatui_toolkit::{ResizableSplit, SplitDirection};
let mut split = ResizableSplit::new(SplitDirection::Horizontal)
.ratio(0.5)
.min_ratio(0.2)
.max_ratio(0.8);
// Handle mouse events
if let Some(event) = split.handle_mouse(mouse_event, area) {
// Split ratio was updated by drag
}
// Render
let [left, right] = split.split(area);
frame.render_widget(left_content, left);
frame.render_widget(right_content, right);
```
### Tree View
```rust
use ratatui_toolkit::{TreeView, TreeViewState, TreeNode};
// Build tree structure
let root = TreeNode::new("root", "Root")
.with_children(vec![
TreeNode::new("child1", "Child 1"),
TreeNode::new("child2", "Child 2")
.with_children(vec![
TreeNode::new("grandchild", "Grandchild"),
]),
]);
let mut state = TreeViewState::new(root);
let tree = TreeView::new(&state);
// Handle navigation
state.handle_key(KeyCode::Down); // Move down
state.handle_key(KeyCode::Right); // Expand
state.handle_key(KeyCode::Left); // Collapse
```
### Toast Notifications
```rust
use ratatui_toolkit::{ToastManager, Toast, ToastLevel, render_toasts};
use std::time::Duration;
let mut manager = ToastManager::new()
.max_toasts(5)
.default_duration(Duration::from_secs(3));
// Add toasts
manager.push(Toast::info("Information message"));
manager.push(Toast::success("Operation completed!"));
manager.push(Toast::warning("Please check your input"));
manager.push(Toast::error("Something went wrong"));
// Update and render
manager.tick(); // Remove expired toasts
render_toasts(frame, area, &manager);
```
### Markdown Rendering
```rust
use ratatui_toolkit::{
render_markdown, render_markdown_with_style, render_markdown_interactive,
MarkdownStyle, MarkdownWidget, MarkdownScrollManager,
};
// Simple rendering
let text = render_markdown("# Title\n\nParagraph with **bold** text.", None);
// Custom styling with syntax highlighting
let style = MarkdownStyle::default();
let text = render_markdown_with_style(markdown_content, &style);
// Interactive widget with scroll management
let mut scroll_manager = MarkdownScrollManager::new();
let widget = MarkdownWidget::new(markdown_content)
.with_style(style);
frame.render_stateful_widget(widget, area, &mut scroll_manager);
```
**Markdown Features:**
- Syntax highlighting for code blocks
- Configurable themes
- Scroll management for long documents
- Expandable/collapsible sections
### Terminal Emulator (TermTui)
```rust
use ratatui_toolkit::{TermTui, TermTuiKeyBindings};
// Spawn a terminal with default shell
let shell = std::env::var("SHELL").unwrap_or("/bin/sh".into());
let mut term = TermTui::spawn_with_command("Terminal", &shell, &[])?;
// Handle input
term.handle_key(key_event);
term.handle_mouse(mouse_event, terminal_area);
// Render
term.render(frame, area);
```
**Default Keybindings:**
- `Ctrl+X` - Enter copy mode
- `Ctrl+Shift+C` - Copy selection
**Copy Mode:**
- `h/j/k/l` or arrows - Navigate
- `v` or `Space` - Start selection
- `y` or `Enter` - Copy and exit
- `w/b` - Word navigation
- `0/$` - Line start/end
- `g/G` - Top/bottom
- `Esc` or `q` - Exit copy mode
## Customizable Keybindings
All interactive components expose their keybindings through configuration structs, allowing full customization:
### TermTui
```rust
use ratatui_toolkit::{TermTui, TermTuiKeyBindings};
use crossterm::event::{KeyCode, KeyModifiers, KeyEvent};
// Create custom keybindings
let mut bindings = TermTuiKeyBindings::default();
bindings.enter_copy_mode = KeyEvent::new(KeyCode::Char('b'), KeyModifiers::CONTROL);
let term = TermTui::spawn_with_command("Terminal", "bash", &[])?
.with_keybindings(bindings);
```
### TreeView
```rust
use ratatui_toolkit::{TreeNavigator, TreeKeyBindings};
use crossterm::event::KeyCode;
let bindings = TreeKeyBindings::new()
.with_next(vec![KeyCode::Char('n'), KeyCode::Down])
.with_previous(vec![KeyCode::Char('p'), KeyCode::Up])
.with_expand(vec![KeyCode::Char('e'), KeyCode::Right])
.with_collapse(vec![KeyCode::Char('c'), KeyCode::Left]);
let navigator = TreeNavigator::with_keybindings(bindings);
```
### Available Keybinding Configs
| TermTui | `TermTuiKeyBindings` | `.with_keybindings()` |
| TreeView | `TreeKeyBindings` | `TreeNavigator::with_keybindings()` |
## Architecture
### Module Structure
All components follow a consistent module organization pattern for maintainability:
```
src/component_name/
├── mod.rs # Type definition only (struct/enum)
├── constructors/ # Constructors and builders (new, with_*, builder)
│ ├── mod.rs
│ ├── new.rs
│ └── with_*.rs
├── methods/ # Instance methods (&self, &mut self)
│ ├── mod.rs
│ └── method_name.rs
└── traits/ # Trait implementations (Widget, Default, etc.)
├── mod.rs
└── trait_name.rs
```
This structure ensures:
- **Single responsibility**: Each file contains one impl block
- **Easy navigation**: Find constructors in `constructors/`, methods in `methods/`
- **Consistent patterns**: All components organized identically
### Component Pattern
All components follow ratatui's `Widget` and `StatefulWidget` patterns:
```rust
// Stateless widget
impl Widget for MyComponent {
fn render(self, area: Rect, buf: &mut Buffer) { ... }
}
// Stateful widget
impl StatefulWidget for MyComponent {
type State = MyComponentState;
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) { ... }
}
```
### Mouse Support
Components support mouse interaction through a consistent API:
```rust
// Handle mouse events
if let Some(action) = component.handle_mouse(mouse_event, area) {
match action {
ComponentAction::Clicked => { ... }
ComponentAction::Dragged { delta } => { ... }
}
}
```
## Comparison with Alternatives
| **ratatui-toolkit** | Comprehensive component library | 17+ components |
| `tui-textarea` | Text editing | Textarea only |
| `tui-tree-widget` | Tree views | Tree only |
| `ratatui-image` | Image rendering | Images only |
## Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
1. Fork the repository
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
3. Commit your changes (`git commit -m 'Add amazing feature'`)
4. Push to the branch (`git push origin feature/amazing-feature`)
5. Open a Pull Request
## License
Licensed under the MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT).