Skip to content

Introduction

ratcn is a component library for Ratatui apps: beautifully designed terminal UI components that you can copy, paste, theme, and own in your application code.

Getting started

The recommended way to set up a terminal project is with the cargo-ratcn CLI:

sh
cargo install cargo-ratcn
cargo new my-app
cd my-app
cargo ratcn init

See Getting started for starter apps and copying components into your project with cargo ratcn add.

Preview status

ratcn is a preview release. It works, and it is documented, but three things are worth knowing before you build on it:

  • The API is unstable. The public surface is still moving. Pin an exact version and expect to edit when you upgrade.
  • The CLI sets up terminal apps and copies components. cargo ratcn init configures terminal Cargo packages and can install a starter only over Cargo's untouched default main.rs; cargo ratcn add copies a built-in component when you want to own its source.
  • Twelve components are available:Button, List, ScrollArea, Select, Tabs, Dialog, Toast, BarChart, Tooltip, Checkbox, Cycle, and Progress.

If there are specific components, patterns, or features you would like to see included, please open an issue.

Two layers, use either one

The library has two layers, and each works on its own:

  • Paint-only widgetsButtonWidget, BarChartWidget, and friends. Ordinary Ratatui widgets that only paint. They drop into any Ratatui app with frame.render_widget(...): no runtime, no message type, no change to how your app already works.
  • Interactive componentsButton, List, Tabs, Dialog, and more. These add focus, keyboard and mouse handling, and messages on top, and are declared through the Ratcn runtime.

If you already have focus and event handling you like, use the widgets alone and keep it. Nothing built that way is second-class — the interactive components paint through the very same widgets — and you can adopt the runtime later, one component at a time.

Your app stays in charge

ratcn does not own your app loop or your state. Your app owns state, events, and updates; the library reads state while rendering and returns messages when something happens. It enters your app at exactly two call sites — remove them and the rest of the loop is untouched:

  • Ratcn::render(frame, area, state, theme, declare) — declare which components are on screen this frame, and paint them.
  • Ratcn::handle_event(event, state) — route one input event and maybe get a message back.

A typical app has three pieces:

PieceRole
AppStateYour state: domain data, form values, selected rows, FocusState, theme, open dialogs.
MsgYour message enum. Components emit these; your update function applies them.
RatcnThe runtime: remembers what was on screen last frame and routes events to it.

Each frame, the closure you pass to Ratcn::render declares the UI: build components from current state, split areas with ordinary Ratatui layouts, and place each interactive component where it is painted. Decorative widgets are painted directly and need no id.

Components never write your state. A Button emits a message when pressed. A List reads its selection from your state and emits the chosen item for you to store. Focus works the same way: a FocusState lives in your AppState, and focus changes come back as a message. Your update function is the only place state changes.

When an event arrives, hand it to handle_event. The result tells you what to do:

ResultMeaning
Emit(msg)A component handled the event and produced an app message — apply it.
ConsumedA component handled the event; nothing for you to do.
IgnoredNo component wanted it; your own shortcuts can have it.

A first app

See Getting started to initialize a terminal project and install the smallest complete app using the runtime.

Styling comes from the theme passed to Ratcn::render, and that is the only styling most apps touch. See Themes for presets and authored palettes.

The concepts

The concept pages each cover one idea in depth. Roughly in reading order:

  • State and messages — the ownership rules: your app owns state, components read it and emit messages, update is the only writer.
  • Rendering and event routing — how a frame is declared, how the runtime remembers it, and how events find the right component.
  • Focus, hover, and identity — how components get stable identities, how Tab traversal works, why focus lives in your state and hover lives in the runtime.
  • Keyboard — every key the components respond to, and the rules that decide which one claims a key.
  • Layers and modals — dialogs, overlays, and paint ordering.
  • Themes — built-in presets and authoring your own palette.
  • Host integration — opening and restoring the terminal with a Session, the event loop shape, and a browser app with ratzilla.
  • Mouse Input and Dragging — enabling mouse support, and how clicks, hover, and drags reach components.
  • Structuring a larger app — splitting state, messages, and rendering per screen once one module is not enough.
  • Custom components — writing your own components with the same powers as the built-ins, composites included.

Component pages under Components cover each built-in component's features with live previews, and Demos lists every runnable example in the repository — including three full applications.