tabitha
An async, event-driven TUI framework built on ratatui and tokio.
Overview
Tabitha provides a clean architecture for building terminal user interfaces with minimal CPU usage. It only redraws in response to events, making it ideal for applications that need to be "quiet" and power-efficient.
Features
- Event-driven: No polling – only responds to terminal events and task messages
- Async tasks: Background tasks communicate via typed message channels
- Builder pattern: Clean, composable application setup
- Tabs support: Built-in tab management with enable/disable support
- Focus management: Navigate between focusable components
- Minimal allocations: Designed for efficiency in hot paths
- Runtime control: Toggle mouse capture, navigate tabs, quit via contexts
Installation
Add tabitha to your Cargo.toml:
[]
= "0.0.1"
= "0.30"
= { = "1", = ["rt-multi-thread", "macros"] }
Quick Start
use ;
use ;
;
async
Core Concepts
Components
Components are the building blocks of your TUI application. Implement the Component trait to create UI elements:
use ;
use ;
Tabs
Register tabs with the application and use the context to draw and navigate them:
use ;
use ;
;
;
// Build with tabs
let app = new
.main_ui
.add_tab
.add_tab
.build?;
Tabs can be enabled/disabled at runtime:
// In your event handler
ctx.tabs.set_enabled; // Disable a tab
ctx.tabs.is_enabled; // Check if enabled
Background Tasks
Create async background tasks that communicate with the UI via typed messages:
use ;
use Duration;
;
// Handle messages in your MainUi
// Register the task
let app = new
.main_ui
.add_task
.build?;
Focus Management
Components can participate in focus navigation:
// Navigate focus in event handlers
if event.is_key
Event Handling
Events are handled through the handle_event method with an EventResult return type:
EventResult::Handled– Event consumed, stop propagationEventResult::Unhandled– Bubble to parent componentEventResult::StopPropagation– Stop propagation without handling
Convenience methods on Event:
event.is_quit // Ctrl+C or Ctrl+Q
event.is_key // Specific key
event.is_key_with_modifiers
event.is_mouse_click // Any mouse click
event.mouse_position // Get (x, y) if mouse event
Configuration
Mouse Capture
Mouse capture can be configured at build time or toggled at runtime:
// At build time
let app = new
.main_ui
.mouse_capture // Disable mouse capture
.build?;
// At runtime
ctx.set_mouse_capture;
let enabled = ctx.mouse_capture_enabled;
Tick Rate
For applications that need periodic updates:
let app = new
.main_ui
.tick_rate // Optional periodic tick
.build?;
Examples
Run the examples to see tabitha in action:
# Counter with background task
# Tab navigation
# Focus management with tables
Optional Features
blocking-tasks– Enable helpers for spawning blocking operations on a dedicated thread pool
[]
= { = "0.0.1", = ["blocking-tasks"] }
Architecture
┌─────────────────────────────────────────────────────────────┐
│ AppBuilder │
│ - main_ui(component) │
│ - add_tab(tab) │
│ - add_task(name, task) │
│ - mouse_capture(bool) │
│ - tick_rate(duration) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ App │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │
│ │ MainUi │ │ TabManager │ │ FocusManager │ │
│ │ (Component) │ │ (Tabs) │ │ (Focus navigation) │ │
│ └─────────────┘ └─────────────┘ └─────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────┐│
│ │ Event Loop ││
│ │ - Terminal events (keyboard, mouse, resize) ││
│ │ - Task messages (via MessageBus) ││
│ │ - Optional tick timer ││
│ └─────────────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Background Tasks │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Task 1 │ │ Task 2 │ │ Task N │ ... │
│ │ (async) │ │ (async) │ │ (async) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └─────────────┼─────────────┘ │
│ │ TaskSender<T> │
│ ▼ │
│ ┌───────────────┐ │
│ │ MessageBus │ ──► MainUi.handle_task_message│
│ └───────────────┘ │
└─────────────────────────────────────────────────────────────┘
License
Licensed under either of:
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.