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 dependencies.
cargo new --bin demo
cd demo
cargo add dioxus
cargo add dioxus-tuiThen, edit your main.rs with the basic template.
#![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 runPress "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.
// 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!"
}
})
}Hot Reload
- Hot reloading allows much faster iteration times inside of rsx calls by interpreting them and streaming the edits.
- It is useful when changing the styling/layout of a program, but will not help with changing the logic of a program.
Setup
Install dioxus-cli.
Usage
- Run:
dx serve --hot-reload --platform desktop- Change some code within a rsx or render macro
- Save and watch the style change without recompiling
Limitations
- The interpreter can only use expressions that existed on the last full recompile. If you introduce a new variable or expression to the rsx call, it will require a full recompile to capture the expression.
- Components, Iterators, and some attributes can contain arbitrary rust code and will trigger a full recompile when changed.