Codewhale Ratatui

Browse the composer, workbar, ocean, themes and creatures, then use the Rust examples to add Codewhale’s terminal components to your app.

Native conversation, composer and Tasks workbar · Underwater truecolor · 104×30Native conversation, composer and Tasks workbar · Underwater truecolor · 40×30Open in the explorer ↓About this composition →

Start with a working app

Type a message, press Enter to echo it, and Esc to exit. The starter connects editable input, the native composer and workbar in one small app.

git clone https://github.com/codewhale-hq/codewhale-ratatui
cd codewhale-ratatui
cargo run --locked --example starter

Rust 1.89+ · MIT license

Add to an existing Ratatui app

Add the library to your Cargo.toml. Use your existing backend, or enable Crossterm for a new app.

[dependencies]
codewhale-ratatui = { git = "https://github.com/codewhale-hq/codewhale-ratatui", rev = "4d5b05ba0709eb850e7415929b51c4db083d1241" }
ratatui = { version = "0.30.2", default-features = false, features = ["std", "crossterm_0_29"] }
crossterm = "0.29"

Detect the theme once when your app starts, then pass it to your draw function. Theme::detect().tui() selects the native terminal palette.

let theme = codewhale_ratatui::Theme::detect().tui();
pub fn draw_composer(
    area: ratatui::layout::Rect,
    buffer: &mut ratatui::buffer::Buffer,
    theme: &codewhale_ratatui::Theme,
    draft: &codewhale_ratatui::TextInputState,
) -> Option<ratatui::layout::Position> {
    use codewhale_ratatui::{NativeComposer, Paint};
    let area = area.intersection(buffer.area);
    if area.is_empty() {
        return None;
    }
    let composer = NativeComposer::new(draft.text())
        .focused(true)
        .cursor(draft.cursor())
        .can_submit(!draft.is_empty())
        .placeholder("Type a line, then press Enter");
    let height = composer.desired_height(area.width, area.height);
    let slot = ratatui::layout::Rect::new(area.x, area.bottom() - height, area.width, height);
    composer.paint(slot, buffer, theme);
    composer.cursor_position(slot)
}
Keep the state
Your app stores drafts, selection, work and a persistent whale Stage.
Render the view
Components paint the facts you supply into your Ratatui frame.
Handle the action
Route input outcomes to your app. Supply elapsed time when motion needs a redraw.

What are you building?

Choose a starting point, or browse every component below.

The live component gallery

Showcase work

Open component page

The native conversation layout, composer and workbar, plus interactive component studies

Loading the preview…
104 × 30dark-truecolor

Rendered by the Rust components with example data. Choose a terminal profile and width to compare their layouts.

Components used

Your app owns state, timing and actions. Components render into the Ratatui frame you supply.