Crate webatui

source ·
Expand description

Run your TUI apps in the browser!

Webatui is a glue crate for running Ratatui-based TUI apps in the broswer with the help of Yew. Currently, this crate is centered around transforming the text-based displays that ratatui generates into HTML DOM-elements. Some interactivity is supported, like hyperlinks, on-click callbacks, and scrolling (both on mobile devices and with a mouse); however, webatui is not a fully interactive terminal yet. Many things, such as cursor location, editing text, etc, are not supported. Other things, like getting keyboard inputs, are possible via the web-sys crate, but there is no direct ability to setup and configure this, yet.

Many of the web-specific details have been abstracted away so that porting existing apps is as easy as possible. To get started, create a struct that will hold your app’s logic, implement the TerminalApp trait for it, and run the run_tui function with an instance of your app.

use ratatui::{prelude::*, widgets::*};
use webatui::prelude::*;

#[derive(PartialEq, Clone)]
struct MyApp {
  title: String,
}

impl TerminalApp for MyApp {
    // This simple app does not update
    type Message = ();

    // This simple app does not update
    fn update(&mut self, _: TermContext<'_, Self>, _: Self::Message) -> bool { false }

    fn render(&self, area: Rect, frame: &mut Frame<'_>) {
        let para = Paragraph::new(self.title.as_str());
        frame.render_widget(para, area);
    }
}

let my_app = MyApp { title: "Hello WWW!".into() };
run_tui(my_app)

Webatui closely follows Yew’s flow for creating and rendering an app. Once create, an app can be updated via a message (which might be generated by a callback). After the app processes its update, it returns whether or not it needs to be re-rendered. The rendering process is split into two sub-steps (the main difference between webataui and yew). In the first step, the app renders widgets into the Terminal. Once rendered and flushed, the YewBackend converts the text into a series of spans. These spans are then used during the next sub-step, hydration. Hydration allows an app to attach additional data that can’t be passed via a widget, namely callbacks and hyperlinks. To mark a stylible element as “in need of hydration”, add the HYDRATION modifier to its style or use the to_hydrate method available via the NeedsHydration trait. Once all the necessary spans have been hydrated, those spans are composed into a series of HTML <pre> tags and rendered into the DOM.

A note about hydration: When a widget is rendered, the YewBackend gets it character-by-character. This limits the backend’s ability to create blocks that need hydrated. So, a multi-line widget will be split into a series of dehydrated spans that will be hydrated individually.

Modules§

  • Contains the terminal backend that transforms the text rendered from ratatui widgets into HTML.
  • Common includes needed when working with this crate.

Structs§

  • A wrapper around Yew’s Context that is passed to methods like TerminalApp::update.
  • In the public API because of the component impl of WebTerminal
  • A container for a TUI app that renders to HTML.

Enums§

Traits§

  • The core user-facing abstraction of this crate. A terminal app is a type that can be wrapped by a WebTerminal and be displayed by Yew.

Functions§

  • Launches the rendering process using the given app state.