An Elixir Terminal User Interface framework.
Drafter provides a complete TUI framework with:
- Widget-based UI components
- Event-driven architecture
- Flexible layout system
- Self-implemented drawing primitives
- Minimal dependencies
defmodule MyApp do
use Drafter.App
def mount(_props) do
%{counter: 0}
end
def render(state) do
Drafter.container([
Drafter.label("Counter: \\#{state.counter}"),
Drafter.button("Click me!", on_click: :increment)
])
end
def handle_event(:increment, state) do
{:ok, %{state | counter: state.counter + 1}}
end
end
Drafter.run(MyApp)
Summary
Functions
Programmatically activate (press) a widget by its ID.
Animate a widget property.
Create a button widget
Create a container widget
Returns the currently active skin atom.
Create a digits widget for displaying large numbers
Create a footer widget
Get the full state of a widget by its ID.
Get the current value of a widget by its ID.
Create a grid widget for layouts
Create a horizontal layout container
Create a label widget
Create a markdown widget
Create a placeholder widget
Query all widgets matching CSS-like selector.
Query a single widget by CSS-like selector.
Create a rule (divider line) widget
Start a TUI application.
Run an app module in an isolated or shared session using pre-started session services.
Send an app event to the active app loop.
Set an interval timer
Switch the active rendering skin.
Switches the active theme by name.
Set a one-time timeout timer
Stop all animations for a widget.
Stop an animation by its reference.
Validate a widget's value. Sends :validate event to widget, triggering its validators.
Create a vertical layout container
Functions
Programmatically activate (press) a widget by its ID.
Animate a widget property.
Properties
:opacity- Opacity (0.0 to 1.0):background- Background color (RGB tuple):color- Foreground color (RGB tuple):offset_x- X offset in cells:offset_y- Y offset in cells
Options
:duration- Animation duration in ms (default: 300):easing- Easing function (default: :ease_out):on_complete- Callback when animation finishes
Easing Functions
:linear, :ease, :ease_in, :ease_out, :ease_in_out,
:ease_in_quad, :ease_out_quad, :ease_in_out_quad,
:ease_in_cubic, :ease_out_cubic, :ease_in_out_cubic,
:ease_in_elastic, :ease_out_elastic,
:ease_in_bounce, :ease_out_bounce, :ease_in_out_bounce,
:ease_in_back, :ease_out_back
Examples
Drafter.animate(:my_button, :opacity, 0.5, duration: 500)
Drafter.animate(:my_label, :background, {255, 0, 0}, duration: 1000, easing: :ease_out)
Create a button widget
Create a container widget
@spec current_skin() :: atom()
Returns the currently active skin atom.
Create a digits widget for displaying large numbers
@spec focus(term()) :: :ok
Get the full state of a widget by its ID.
Returns the complete widget state struct, useful for accessing multiple fields or widget-specific data.
Returns nil if widget not found.
Get the current value of a widget by its ID.
Returns the primary "value" of the widget:
- TextInput/TextArea: the text string
- Checkbox: boolean (checked?)
- Switch: boolean (enabled?)
- RadioSet: the selected option ID
- SelectionList: list of selected option IDs
- OptionList: the selected option ID
- Collapsible: boolean (expanded?)
- TabbedContent: the active tab index
- DataTable: list of selected row indices
- Tree: list of selected node IDs
Returns nil if widget not found.
Create a grid widget for layouts
Create a horizontal layout container
Create a label widget
Create a markdown widget
Create a placeholder widget
Query all widgets matching CSS-like selector.
Returns list of widget_ids.
Query a single widget by CSS-like selector.
Selector examples:
- "Button" - first Button widget
- "#submit" - widget with id :submit
- ".primary" - widget with class :primary
- "Button.primary" - Button with class :primary
Returns widget_id or nil if not found.
Create a rule (divider line) widget
Start a TUI application.
Options:
:scroll_optimization-true(default) uses a fast render path during scroll gestures (render_hierarchyfrom ETS) and defers a fullrender_appuntil 150 ms after the last scroll event. Set tofalseto disable and trigger a fullrender_appon every scroll tick — maximum freshness at the cost of higher CPU during scroll.:syntax_highlighting-trueto enable tree-sitter syntax highlighting.
Run an app module in an isolated or shared session using pre-started session services.
session_ctx must contain: event_manager, compositor, screen_manager,
theme_manager, event_handler as pid values.
Options:
:mode-:isolated(default) or:shared:shared_state- pid of SharedState server when mode is:shared- All other opts are passed as mount props to the app module
Send an app event to the active app loop.
Used by modal screens and sub-screens to communicate results back to the
parent application via handle_event/3.
@spec set_interval(pos_integer(), atom()) :: :ok
Set an interval timer
@spec set_skin(atom()) :: :ok
Switch the active rendering skin.
The skin controls which characters Drafter.CharacterSet returns for every
widget render. Built-in skins: :graphical (default), :wireframe, :ascii.
Can be called from inside handle_event/2 or on_timer/2 — takes effect on
the next frame.
@spec set_theme(String.t()) :: :ok
Switches the active theme by name.
@spec set_timeout(pos_integer(), atom()) :: :ok
Set a one-time timeout timer
@spec stop_all_animations(atom()) :: :ok
Stop all animations for a widget.
@spec stop_animation(reference()) :: :ok
Stop an animation by its reference.
Validate a widget's value. Sends :validate event to widget, triggering its validators.
Create a vertical layout container