TermUI
A direct-mode Terminal UI framework for Elixir/BEAM, inspired by BubbleTea (Go) and Ratatui (Rust).
TermUI leverages BEAM's unique strengths—fault tolerance, actor model, hot code reloading—to build robust terminal applications using The Elm Architecture.
Features
- Elm Architecture - Predictable state management with
init/update/view - Rich Widget Library - Gauges, tables, menus, charts, dialogs, and more
- Efficient Rendering - Double-buffered differential updates at 60 FPS
- Themable - True color RGB support (16 million colors)
- Cross-Platform - Linux, macOS, Windows 10+ terminal support
- OTP Integration - Supervision trees, fault tolerance, hot code reload
Installation
Add term_ui to your dependencies in mix.exs:
def deps do
[
{:term_ui, "~> 0.1.0"}
]
endQuick Start
defmodule Counter do
use TermUI.Elm
alias TermUI.Event
alias TermUI.Renderer.Style
def init(_opts), do: %{count: 0}
def event_to_msg(%Event.Key{key: :up}, _state), do: {:msg, :increment}
def event_to_msg(%Event.Key{key: :down}, _state), do: {:msg, :decrement}
def event_to_msg(%Event.Key{key: "q"}, _state), do: {:msg, :quit}
def event_to_msg(_, _), do: :ignore
def update(:increment, state), do: {%{state | count: state.count + 1}, []}
def update(:decrement, state), do: {%{state | count: state.count - 1}, []}
def update(:quit, state), do: {state, [:quit]}
def view(state) do
stack(:vertical, [
text("Counter Example", Style.new(fg: :cyan, attrs: [:bold])),
text("", nil),
text("Count: #{state.count}", nil),
text("", nil),
text("↑/↓ to change, Q to quit", Style.new(fg: :bright_black))
])
end
end
# Run the application
TermUI.Runtime.run(root: Counter)Documentation
User Guides
| Guide | Description |
|---|---|
| Overview | Introduction to TermUI concepts |
| Getting Started | First steps and setup |
| Elm Architecture | Understanding init/update/view |
| Events | Handling keyboard and mouse input |
| Styling | Colors, attributes, and themes |
| Layout | Arranging components on screen |
| Widgets | Using built-in widgets |
| Terminal | Terminal capabilities and modes |
| Commands | Side effects and async operations |
Developer Guides
| Guide | Description |
|---|---|
| Architecture Overview | System layers and design |
| Runtime Internals | GenServer event loop and state |
| Rendering Pipeline | View to terminal output stages |
| Event System | Input parsing and dispatch |
| Buffer Management | ETS double buffering |
| Terminal Layer | Raw mode and ANSI sequences |
| Elm Implementation | Elm Architecture for OTP |
| Creating Widgets | How to build and contribute widgets |
| Testing Framework | Component and widget testing |
Examples
The examples/ directory contains standalone applications demonstrating each widget:
| Example | Description |
|---|---|
| dashboard | System monitoring dashboard with multiple widgets |
| gauge | Progress bars and percentage indicators |
| sparkline | Inline data visualization |
| bar_chart | Horizontal and vertical bar charts |
| line_chart | Braille-based line charts |
| table | Scrollable data tables with selection |
| menu | Nested menus with keyboard navigation |
| tabs | Tab-based navigation |
| dialog | Modal dialogs with buttons |
| viewport | Scrollable content areas |
| canvas | Free-form drawing with box/braille characters |
# Run any example
cd examples/dashboard
mix deps.get
mix run run.exsRequirements
- Elixir 1.15+
- OTP 28+ (required for native raw terminal mode)
- Terminal with Unicode support
License
MIT License - see LICENSE for details.