Examples
Four runnable examples live in examples/. They are the source of truth — every
snippet in this book is lifted from them. The small ones are three files —
app.rs (all the tui-pages wiring), ui.rs (pure rendering that only reads
state), and main.rs (the event loop). The full example grows into the
per-page layout from Structuring a Bigger App: a directory
per page, each split by concern.
Run any of them with:
cd examples/<name>
cargo run
minimal
The smallest real app: two pages (Home / About), two buttons, Tab to move, Enter to activate, Ctrl+C to quit. Read this first — it's walked through in full in Getting Started.
Teaches: views, a handler that returns effects, PageSpec with buttons, the
event loop.
| Key | Action |
|---|---|
Tab / Shift+Tab | move focus |
Enter | activate the focused button |
Ctrl+C | quit |
buffers
Three views (Editor / Terminal / Docs) as cyclable buffers, plus pane splitting.
The handler is one match from action to effect — no buffer bookkeeping. Uses
FocusWrap::Wrap so cycling past the ends comes back around.
Teaches: Navigate / NextBuffer / CloseBuffer, SplitPane / NextPane /
ClosePane, and rendering a split layout from tui.buffer. See
Navigation, Buffers & Panes.
| Key | Action |
|---|---|
1 2 3 | open / switch to a buffer |
Tab / Shift+Tab | cycle buffer history |
w | close the active buffer |
v / s | split vertical / horizontal |
o / p | next / previous pane |
x | close the active pane |
Ctrl+C | quit |
full
Everything at once: navigation, a section with selectable items, multi-key chord
sequences (g h, g n, g ?), buffers, panes, and a :-style command palette
built entirely from app state plus the public command resolver.
It's also laid out the way a real app should be. The common code sits at the
src root — app.rs (shared types + the two routers), ui.rs (shared chrome
like the tabs and status bar), main.rs (the loop). Then each page is its own
directory, split by concern:
src/
main.rs event loop
app.rs shared types + routers + build()
ui.rs shared chrome (tabs, workspace, status, palette) + render_button
home/
mod.rs
page.rs tui-pages wiring: page_spec + handle
logic.rs home's own data + decisions (no tui-pages, no ratatui)
ui.rs home's rendering
notes/ mod.rs · page.rs · logic.rs · ui.rs
help/ mod.rs · page.rs · ui.rs (static page — no logic to split out)
Only page.rs touches the library; logic.rs is plain Rust (the note list, the
"which button goes where" decision); ui.rs is plain ratatui; mod.rs is just
glue so the routers can call home::page_spec / home::ui::render. A page only
gets a logic.rs when it has logic worth separating — Help is just text, so it
doesn't. Open a page's folder and you have that whole feature in front of you.
Adding a page is a new directory plus one arm in each router. This is
Structuring a Bigger App made concrete.
Teaches: per-page structure + routing, sections + Activate / LeaveSection,
chord sequences, and composing a command palette (the crate ships no palette —
you build one). See Focus and Commands.
| Key | Action |
|---|---|
Tab / j / k / arrows | move focus (and within a section) |
Enter | activate / select |
Esc | leave the current section |
g h / g n / g ? | go to Home / Notes / Help |
] / [ / x | next / previous / close buffer |
Ctrl+S / Ctrl+D | split vertical / horizontal |
Ctrl+N / Ctrl+W | next pane / close pane |
: | open the command palette |
Ctrl+C | quit |
minimal_dialog
A confirmation dialog using the dialog feature: highlight "Delete an item",
press Enter, confirm or cancel a modal. The handler only opens the dialog;
dialog::handle_key drives it and hands back the result.
Teaches: the modal payload slot M, DialogData::show_intent, dialog::handle_key,
and render_dialog. See Dialogs. Run it with the feature on —
the example's Cargo.toml already enables it.
| Key | Action |
|---|---|
Tab / Shift+Tab | move focus / dialog buttons |
Enter | activate / confirm |
Esc | dismiss the dialog |
Ctrl+C | quit |