Terminal UI
You can build a text-based interface that will run in the terminal using Dioxus.
Note: this book was written with HTML-based platforms in mind. You might be able to follow along with TUI, but you'll have to adapt a bit.
Support
TUI support is currently quite experimental. But, if you're willing to venture into the realm of the unknown, this guide will get you started.
- It uses flexbox for the layout
- It only supports a subset of the attributes and elements
- Regular widgets will not work in the tui render, but the tui renderer has its own widget components that start with a capital letter. See the widgets example
- 1px is one character line height. Your regular CSS px does not translate
- If your app panics, your terminal is wrecked. This will be fixed eventually
Getting Set up
Start by making a new package and adding Dioxus and the TUI renderer as dependancies.
cargo new --bin demo cd demo cargo add dioxus cargo add dioxus-tui
Then, edit your main.rs
with the basic template.
src/hello_world_tui.rs
#![allow(non_snake_case)] // import the prelude to get access to the `rsx!` macro and the `Scope` and `Element` types use dioxus::prelude::*; fn main() { // launch the app in the terminal dioxus_tui::launch(App); } // create a component that renders a div with the text "Hello, world!" fn App(cx: Scope) -> Element { cx.render(rsx! { div { "Hello, world!" } }) }
To run our app:
cargo run
Press "ctrl-c" to close the app. To switch from "ctrl-c" to just "q" to quit you can launch the app with a configuration to disable the default quit and use the root TuiContext to quit on your own.
src/hello_world_tui_no_ctrl_c.rs
// todo remove deprecated #![allow(non_snake_case, deprecated)] use dioxus::events::{KeyCode, KeyboardEvent}; use dioxus::prelude::*; use dioxus_tui::TuiContext; fn main() { dioxus_tui::launch_cfg( App, dioxus_tui::Config::new() .without_ctrl_c_quit() // Some older terminals only support 16 colors or ANSI colors // If your terminal is one of these, change this to BaseColors or ANSI .with_rendering_mode(dioxus_tui::RenderingMode::Rgb), ); } fn App(cx: Scope) -> Element { let tui_ctx: TuiContext = cx.consume_context().unwrap(); cx.render(rsx! { div { width: "100%", height: "10px", background_color: "red", justify_content: "center", align_items: "center", onkeydown: move |k: KeyboardEvent| if let KeyCode::Q = k.key_code { tui_ctx.quit(); }, "Hello world!" } }) }