reratui 0.2.0

A modern, reactive TUI framework for Rust with React-inspired hooks and components, powered by ratatui
Documentation

Reratui

A Modern, Reactive TUI Framework for Rust

Crates.io Documentation License Build Status

Build beautiful, interactive terminal applications with React-inspired components and hooks

Getting Started β€’ Documentation β€’ Examples β€’ Contributing


Overview

Reratui brings modern web development patterns to terminal user interfaces. Inspired by React, it provides a component-based architecture with hooks, enabling you to build complex, stateful TUI applications with clean, maintainable code.

Why Reratui?

  • 🎨 Declarative UI - Build interfaces with JSX-like syntax using the rsx! macro
  • πŸͺ React-Style Hooks - Manage state and side effects with familiar patterns
  • ⚑ High Performance - Zero-cost abstractions with compile-time optimizations
  • πŸ”’ Type-Safe - Leverage Rust's type system for compile-time correctness
  • πŸ”„ Async-First - Built on Tokio with first-class async/await support
  • 🧩 Modular - Compose complex UIs from simple, reusable components

✨ Features

πŸ—οΈ Component System

  • Component-based architecture with lifecycle hooks
  • Reusable, composable components
  • Type-safe props with #[derive(Props)]
  • Automatic prop validation

πŸͺ Comprehensive Hooks

  • State management (use_state, use_reducer)
  • Side effects (use_effect, use_async_effect)
  • Performance (use_memo, use_callback)
  • Events (keyboard, mouse, resize)

🎯 Developer Experience

  • JSX-like rsx! macro syntax
  • Compile-time hook rules validation
  • Comprehensive error messages
  • Hot-reload support (coming soon)

⚑ Performance

  • Zero-cost abstractions
  • Compile-time macro expansion
  • Efficient event handling
  • Minimal runtime overhead
Category Hook Description
State use_state Local component state management
use_reducer Complex state logic with actions (Redux-style)
use_ref Mutable references that persist across renders
Effects use_effect Side effects with dependency tracking
use_effect_once Run effect only on mount
use_async_effect Async side effects with cleanup
Performance use_callback Memoized callbacks to prevent re-renders
use_memo Memoized computed values
use_effect_event Stable event handlers with latest values
Context use_context Access shared data without prop drilling
use_context_provider Provide context values to children
Events use_event Generic terminal event handling
use_keyboard Keyboard events with stable callbacks
use_keyboard_press Handle key press events only
use_keyboard_shortcut Specific key combinations
use_mouse Mouse events with stable callbacks
use_mouse_click Handle mouse click events
use_mouse_drag Track drag operations
use_double_click Detect double-click gestures
on_global_event Global keyboard event handlers
Layout use_frame Frame timing and render context
use_area Component's rendering area
use_on_resize Handle terminal resize events
use_terminal_dimensions Current terminal size

πŸš€ Installation

Add Reratui to your Cargo.toml:

[dependencies]
reratui = "0.1.0"
tokio = { version = "1", features = ["full"] }

Note: The main reratui crate re-exports all necessary functionality. You typically don't need to add individual sub-crates.

πŸ“– Quick Start

Your First Component

use reratui::prelude::*;

#[component]
fn Counter() -> Element {
    let (count, set_count) = use_state(|| 0);

    // Handle keyboard events
    if let Some(Event::Key(key)) = use_event()
        && key.is_press()
    {
        match key.code {
            KeyCode::Char('j') => set_count.update(|n| n + 1),
            KeyCode::Char('k') => set_count.update(|n| n - 1),
            KeyCode::Char('r') => set_count.set(0),
            _ => {}
        }
    }

    rsx! {
        <Block
            title="Counter Demo"
            borders={Borders::ALL}
            border_style={Style::default().fg(Color::Cyan)}
        >
            <Paragraph alignment={Alignment::Center}>
                {format!("Count: {}", count.get())}
            </Paragraph>
            <Paragraph alignment={Alignment::Center}>
                {"Press 'j' to increment, 'k' to decrement, 'r' to reset"}
            </Paragraph>
        </Block>
    }
}

#[reratui::main]
async fn main() -> Result<()> {
    render(|| rsx! { <Counter /> }).await?;
    Ok(())
}

Component with Props

use reratui::prelude::*;

#[derive(Props)]
struct ButtonProps {
    label: String,
    on_click: Option<Callback<()>>,
}

#[component]
fn Button(props: &ButtonProps) -> Element {
    rsx! {
        <Block borders={Borders::ALL}>
            <Paragraph alignment={Alignment::Center}>
                {format!("[ {} ]", props.label)}
            </Paragraph>
        </Block>
    }
}

#[component]
fn App() -> Element {
    let (clicks, set_clicks) = use_state(|| 0);

    rsx! {
        <Layout direction={Direction::Vertical}>
            <Button
                label={format!("Clicked {} times", clicks.get())}
                on_click={move |_| set_clicks.update(|n| n + 1)}
            />
        </Layout>
    }
}

πŸŽ“ Advanced Usage

Complex State with Reducers

use reratui::prelude::*;

#[derive(Clone)]
enum TodoAction {
    Add(String),
    Toggle(usize),
    Remove(usize),
}

#[derive(Clone)]
struct TodoState {
    todos: Vec<Todo>,
    next_id: usize,
}

fn todo_reducer(state: TodoState, action: TodoAction) -> TodoState {
    match action {
        TodoAction::Add(text) => TodoState {
            todos: {
                let mut todos = state.todos;
                todos.push(Todo { id: state.next_id, text, completed: false });
                todos
            },
            next_id: state.next_id + 1,
        },
        TodoAction::Toggle(id) => TodoState {
            todos: state.todos.into_iter().map(|mut todo| {
                if todo.id == id {
                    todo.completed = !todo.completed;
                }
                todo
            }).collect(),
            ..state
        },
        TodoAction::Remove(id) => TodoState {
            todos: state.todos.into_iter().filter(|t| t.id != id).collect(),
            ..state
        },
    }
}

#[component]
fn TodoApp() -> Element {
    let (state, dispatch) = use_reducer(
        todo_reducer,
        TodoState { todos: vec![], next_id: 1 }
    );

    // Use state and dispatch in your component...
}

Context for Global State

Share state across components without prop drilling:

#[component]
fn App() -> Element {
    let theme = use_context_provider(|| Theme::Dark);

    rsx! {
        <Layout>
            <Header />
            <Content />
        </Layout>
    }
}

#[component]
fn Header() -> Element {
    let theme = use_context::<Theme>();
    // Use theme...
}

πŸ›οΈ Architecture

Reratui follows a modular, layered architecture with clear separation of concerns:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚           reratui (Main Crate)              β”‚  ← Public API
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  reratui-macro  β”‚  reratui-hooks            β”‚  ← Developer Tools
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚  reratui-core   β”‚  reratui-runtime          β”‚  ← Core Engine
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚         reratui-ratatui (Backend)           β”‚  ← Rendering
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Crate Structure

Crate Purpose
reratui Main crate - re-exports all functionality
reratui-core Core types (Element, Component, VNode)
reratui-macro Procedural macros (#[component], rsx!, Props)
reratui-hooks Hook implementations and state management
reratui-runtime Event loop, lifecycle, and rendering runtime
reratui-ratatui Ratatui backend integration

Design Principles

Principle Implementation
SOLID Single responsibility, interface segregation, dependency inversion
DDD Clear domain boundaries with well-defined interfaces
Composition Build complex UIs by composing simple components
Type Safety Leverage Rust's type system for compile-time correctness
Zero-Cost No runtime overhead for abstractions

πŸ’‘ Examples

Explore complete, runnable examples in the examples/ directory:

Example Description Command
counter Basic state management and keyboard events cargo run --example counter
rsx_demo Comprehensive RSX macro features cargo run --example rsx_demo
events_showcase Complete event handling (keyboard, mouse, resize) cargo run --example events_showcase
router Navigation and routing Coming soon

πŸ“š Documentation

Resource Description
API Docs Complete API reference with examples
Examples Working code examples and demos
Hooks Guide Detailed hook usage patterns
Component Patterns Best practices and design patterns

πŸ”§ Requirements

Minimum Supported Rust Version (MSRV): 1.75.0

Required for:

  • let-else statements
  • let chains in if expressions
  • Edition 2024 features

🀝 Contributing

We welcome contributions! See our Contributing Guide for:

  • πŸ“œ Code of conduct
  • πŸ› οΈ Development setup
  • βœ… Testing requirements
  • πŸ”„ Pull request process

πŸ—ΊοΈ Roadmap

βœ… Completed

  • Core component system with lifecycle hooks (on_mount, on_unmount)
  • Comprehensive hooks system (state, effect, reducer, context)
  • RSX macro with conditional rendering
  • Hook rules validation at compile-time
  • Event handling (keyboard, mouse, resize)
  • Global event system for application-wide shortcuts

🚧 In Progress

  • Router with nested routes
  • Form validation helpers
  • Animation system

πŸ“‹ Planned

  • Dev tools and debugging utilities
  • Performance profiling tools
  • Hot-reload support
  • Component testing utilities

πŸ“„ License

Dual-licensed under your choice of:

Unless explicitly stated otherwise, any contribution intentionally submitted for inclusion shall be dual licensed as above, without additional terms or conditions.


πŸ™ Acknowledgments

Reratui stands on the shoulders of giants:

  • Ratatui - The powerful TUI library that powers our rendering
  • React - Inspiration for component architecture and hooks patterns
  • Yew - Rust web framework with similar design patterns

Built with ❀️ by the Rust community

⭐ Star us on GitHub β€’ πŸ“– Read the Docs β€’ πŸ’¬ Join Discussions