API Reference¶
Complete reference for all public types, functions, and constants in maya.
Table of Contents¶
- App Framework (run, Program, Cmd, Sub, key_map)
- DSL Nodes
- DSL Style Tags
- DSL Layout Tags
- DSL Runtime Pipes
- DSL Factory Functions
- DSL Constants
- Element Types
- Style System
- Color
- Theme
- Border
- Layout Types
- Event System
- Event Predicates
- Signals
- Canvas
- Widgets
- Core Types
App Framework¶
run\<P>()¶
The primary entry point for interactive apps. P must satisfy the Program
concept (see below). The runtime owns the event loop, calling P::update on
each message and re-rendering via P::view.
Program concept¶
template <typename P>
concept Program = requires {
typename P::Model;
typename P::Msg;
} && (HasFullInit<P> || HasSimpleInit<P>)
&& requires(P::Model m, P::Msg msg) {
{ P::update(std::move(m), std::move(msg)) } -> std::convertible_to<std::pair<P::Model, Cmd<P::Msg>>>;
} && requires(const P::Model& m) {
{ P::view(m) } -> std::convertible_to<Element>;
};
A Program is a struct with:
- Model — the app state type (plain data)
- Msg — a std::variant of all possible messages
- init() — returns Model (simple) or std::pair<Model, Cmd<Msg>> (full)
- update(Model, Msg) — returns std::pair<Model, Cmd<Msg>>
- view(const Model&) — returns Element
- subscribe(const Model&) (optional) — returns Sub<Msg>
Cmd\<Msg>¶
template <typename Msg>
class Cmd {
static Cmd none();
static Cmd quit();
static Cmd batch(std::vector<Cmd> cmds); // also variadic
static Cmd after(std::chrono::milliseconds delay, Msg msg);
static Cmd task(std::function<void(std::function<void(Msg)>)> fn);
static Cmd task_isolated(...); // detached thread
static Cmd set_title(std::string title);
static Cmd write_clipboard(std::string text);
static Cmd query_clipboard();
// Interactive-child escape hatch (see below).
template <std::invocable F> static Cmd suspend(F&& run);
// Inline scrollback control (see docs/internals/witness-chain.md).
static Cmd commit_scrollback(ScrollbackDebt debt);
static Cmd commit_scrollback_overflow();
static Cmd force_redraw();
static Cmd reset_inline();
};
Commands represent side effects. Cmd<Msg>{} (or Cmd::none()) means no
effect. Cmd::quit() exits the app. Cmd::batch() combines multiple commands.
Cmd::after() sends a delayed message. Cmd::task() runs an async function
that may produce a message.
Cmd::suspend() — hand the real terminal to an interactive child¶
template <std::invocable F>
requires std::convertible_to<std::invoke_result_t<F>, Msg>
static Cmd suspend(F&& run);
Suspends the TUI and hands the real terminal to run — the escape hatch
for interactive children (sudo password prompts, $EDITOR, pagers). The
runtime tears the TUI down to a clean, cooked (line-disciplined) tty, calls
run() synchronously on the UI thread — the user is interacting with the
child, so there is nothing else to do — then restores raw mode + the TUI
escapes, re-anchors the renderer (inline: a fresh serialize below the child's
output; fullscreen: a full repaint), and dispatches the Msg that run
returned so update() can fold the child's result back into the model.
run returning a Msg (rather than void) is what closes the loop: the
callable typically spawns the child with inherited stdio, tees its output to a
buffer, and returns a completion Msg carrying the exit code + captured bytes.
return Cmd<Msg>::suspend([] {
int rc = std::system("sudo -v"); // child owns the tty here
return Msg{SudoDone{ .code = rc }}; // folded back after restore
});
See the Cmd::suspend demo in d726f07 and App::suspend in
maya/app/app.hpp.
Sub\<Msg>¶
template <typename Msg>
class Sub {
static Sub none();
static Sub batch(std::vector<Sub> subs); // also variadic: batch(a, b, c)
static Sub on_key(std::function<std::optional<Msg>(const KeyEvent&)> fn);
static Sub on_mouse(std::function<std::optional<Msg>(const MouseEvent&)> fn);
static Sub on_resize(std::function<Msg(Size)> fn);
static Sub on_paste(std::function<Msg(std::string)> fn);
static Sub every(std::chrono::milliseconds interval, Msg msg);
static Sub on_animation_frame(Msg msg); // sugar for every(16ms, msg)
};
Subscriptions declare which external events the app listens to. Returned from
the optional subscribe(const Model&) method. Subscriptions are re-evaluated
when the model changes, enabling conditional subscriptions (e.g. only tick
while a timer is running).
on_animation_frame() is every(16ms, msg) under one shared timer engine —
there is no separate animation pump. Drop the subscription from subscribe()
and the ticks stop; the loop returns to idle wait with zero bytes per frame.
Animation-frame requests¶
The redraw-only counterpart to Sub::on_animation_frame. A widget calls it
from its build() each frame it wants to keep animating; the run loop folds
these requests into the same wake schedule as Sub::Every timers. The
distinction is intent, not mechanism: Every delivers a Msg (drives
update → model), a frame request only asks for a repaint — pure visual
layer (cursor blink, scramble caret, fade) that reads wall-clock in build()
and mutates nothing. A widget that stops calling drops out of the next
collection and the loop idles. Idempotent within a frame.
key_map\<Msg>() and key predicates¶
using KeySpec = std::variant<char, SpecialKey>;
template <typename Msg>
Sub<Msg> key_map(std::initializer_list<std::pair<KeySpec, Msg>> entries);
// Pure predicates for use inside subscribe() / on_key filters:
bool key_is(const KeyEvent& k, char c) noexcept; // also char32_t / SpecialKey
bool ctrl_is(const KeyEvent& k, char c) noexcept; // Ctrl+c, not Ctrl+Alt+c
bool alt_is(const KeyEvent& k, char c) noexcept; // Alt+c, not Ctrl+Alt+c
key_map() builds a Sub::on_key from a declarative key→message table:
The *_is predicates are the building blocks for hand-written on_key
filters where a table isn't expressive enough (modifiers, ranges).
RunConfig¶
struct RunConfig {
std::string_view title = "";
int fps = 0; // 0 = event-driven
bool mouse = false;
Mode mode = Mode::Fullscreen;
Theme theme = theme::dark;
};
run() — Simple Convenience API¶
template <SimpleEventFn EventFn, SimpleRenderFn RenderFn>
void run(RunConfig cfg, EventFn&& event_fn, RenderFn&& render_fn);
template <SimpleEventFn EventFn, SimpleRenderFn RenderFn>
void run(EventFn&& event_fn, RenderFn&& render_fn); // default RunConfig
A closure-based entry point that requires no boilerplate. Suitable for most
interactive apps that don't need the full Elm-architecture of run<P>().
Event function: (const Event&) -> bool (returning false quits) or
(const Event&) -> void (call quit() to exit).
Render function: () -> Element or (const Ctx&) -> Element.
Global control — quit() / set_mouse()¶
// maya/app/quit.hpp
void quit() noexcept; // request a clean exit from run() / live()
void set_mouse(bool on) noexcept; // toggle mouse capture at runtime
set_mouse() flips terminal mouse reporting on/off while the app runs — off
hands the scroll wheel back to the terminal (native scrollback), on recaptures
clicks/drag/wheel. The request is applied on the next loop iteration and keeps
the runtime's mouse state in sync for a clean terminal restore on exit. Works
from run() event functions and from a Program's update()/subscribe().
For Program apps Cmd<Msg>::quit() is preferred over quit(); there is no
Cmd form of set_mouse() yet, so call the free function. See
Events → Mouse capture vs. native terminal scroll.
Ctx¶
The Ctx overload of the render function is useful for adaptive layouts that
need to inspect the terminal size or current theme at render time.
live()¶
LiveConfig¶
canvas_run()¶
Status canvas_run(
CanvasConfig cfg,
std::function<void(StylePool&, int w, int h)> on_resize,
std::function<bool(const Event&)> on_event,
std::function<void(Canvas&, int w, int h)> on_paint);
CanvasConfig¶
struct CanvasConfig {
int fps = 60;
bool mouse = false;
Mode mode = Mode::Fullscreen;
std::string title;
};
print()¶
quit()¶
In Program apps, prefer
Cmd<Msg>::quit()fromupdate()instead of callingquit()directly. The free function is still available forlive()andcanvas_run()apps.
DSL Nodes¶
All nodes satisfy the Node concept:
template <typename T>
concept Node = requires(const T& n) {
{ n.build() } -> std::convertible_to<Element>;
};
template <typename T>
concept DslChild = Node<T> || ElementRange<T>;
DslChild is what v() and h() accept — either a Node (compile-time or
runtime) or an ElementRange (e.g. std::vector<Element>).
TextNode¶
Created via t<"...">.
RuntimeTextNode¶
template <typename S>
struct RuntimeTextNode {
S content;
Style style{};
TextWrap wrap{TextWrap::Wrap};
operator Element() const;
Element build() const;
};
Created via text(). Supports | Bold, | Fg<R,G,B>, etc.
BoxNode¶
template <FlexDirection Dir, BoxCfg Cfg, typename... Children>
struct BoxNode {
std::tuple<Children...> children;
Element build() const;
};
Created via v() and h(). Supports layout pipes.
DynNode¶
Created via dyn().
MapNode¶
template <typename R, typename Proj>
struct MapNode {
R range;
Proj proj;
Element build() const; // Iterates range, applies proj
};
Created via map().
SpacerNode¶
SepNode¶
VSepNode¶
BlankNode¶
DSL Style Tags¶
inline constexpr StyTag<...> Bold;
inline constexpr StyTag<...> Dim;
inline constexpr StyTag<...> Italic;
inline constexpr StyTag<...> Underline;
inline constexpr StyTag<...> Strike;
inline constexpr StyTag<...> Inverse;
template <uint8_t R, uint8_t G, uint8_t B>
inline constexpr StyTag<...> Fg;
template <uint8_t R, uint8_t G, uint8_t B>
inline constexpr StyTag<...> Bg;
DSL Layout Tags¶
template <int T, int R = T, int B = T, int L = R>
inline constexpr PadTag<T,R,B,L> pad;
template <int G>
inline constexpr GapTag<G> gap_;
template <BorderStyle BS>
inline constexpr BorderTag<BS> border_;
template <uint8_t R, uint8_t G, uint8_t B>
inline constexpr BColTag<R,G,B> bcol; // Requires border first
template <int G = 1>
inline constexpr GrowTag<G> grow_;
template <int W>
inline constexpr WidthTag<W> w_; // fixed width; also wraps text nodes
template <int H>
inline constexpr HeightTag<H> h_; // fixed height
DSL Runtime Pipes¶
Runtime pipe tags for dynamic values. Same | syntax as compile-time pipes.
Layout Pipes¶
| Function | Tag Type | Description |
|---|---|---|
padding(int) / padding(int,int) / padding(int,int,int,int) |
RPad |
Runtime padding |
gap(int) |
RGap |
Gap between children |
margin(int) / margin(int,int) / margin(int,int,int,int) |
RMargin |
Outer margin |
grow(float g = 1.0f) |
RGrow |
Flex grow factor |
width(int) |
RWidth |
Fixed width |
height(int) |
RHeight |
Fixed height |
Border Pipes¶
| Function | Tag Type | Description |
|---|---|---|
border(BorderStyle) |
RBorder |
Border style |
bcolor(Color) |
RBCol |
Border color |
btext(string, pos = Top, align = Start) |
RBText |
Border text label (pos/align default) |
Style Pipes¶
| Function | Tag Type | Description |
|---|---|---|
fgc(Color) |
RFg |
Foreground color |
bgc(Color) |
RBg |
Background color |
Alignment Pipes¶
| Function | Tag Type | Description |
|---|---|---|
align(Align) |
RAlign |
Cross-axis alignment |
justify(Justify) |
RJust |
Main-axis distribution |
overflow(Overflow) |
ROvf |
Overflow behavior |
Scroll Pipes¶
Wrap content in a scroll viewport backed by a caller-owned ScrollState. The
renderer applies the scroll offset and writes max_x/max_y back after layout
so clamping is automatic.
| Function | Description |
|---|---|
scroll(ScrollState&) |
Scroll on both axes, viewport = allocated size |
scroll(ScrollState&, int viewport_h) |
Vertical scroll, fixed viewport height |
scroll(ScrollState&, int w, int h) |
Both axes, fixed viewport w×h |
scrolly(ScrollState&, int h) |
Vertical-only scroll, fixed height |
scrollx(ScrollState&, int w) |
Horizontal-only scroll, fixed width |
Text-Wrap Tags¶
| Tag | Effect on a text(...) node |
|---|---|
clip |
TextWrap::TruncateEnd — hard-truncate at the box edge |
nowrap |
TextWrap::NoWrap — overflow past the edge, never wrap |
WrappedNode¶
Created automatically when a runtime pipe is applied to any Node. Satisfies Node.
Multiple runtime pipes chain onto the same WrappedNode without extra nesting.
DSL Factory Functions¶
// Compile-time text
template <Str S>
inline constexpr TextNode<S> t;
// Vertical stack — accepts Nodes and ElementRanges (e.g. vector<Element>)
template <DslChild... Cs>
constexpr auto v(Cs... cs) -> BoxNode<Column, BoxCfg{}, Cs...>;
// Horizontal stack — accepts Nodes and ElementRanges (e.g. vector<Element>)
template <DslChild... Cs>
constexpr auto h(Cs... cs) -> BoxNode<Row, BoxCfg{}, Cs...>;
// Runtime builders (promoted from detail namespace)
auto box() -> BoxBuilder; // Base builder
auto vstack() -> BoxBuilder; // Column direction
auto hstack() -> BoxBuilder; // Row direction
auto center() -> BoxBuilder; // Centered, grow=1
// Z-stack — layer children on top of one another
Element zstack(std::vector<Element> layers);
// Measure-aware component: receives the (width, height) it was allotted
Element component(std::function<Element(int w, int h)> fn);
// Empty element (renders nothing, satisfies Node)
Element nothing();
// Zero-copy references (no element copy): render an externally-owned
// element vector / sealed ScrollbackLedger in place
Element list_ref(const std::vector<Element>* items);
Element ledger_ref(const ScrollbackLedger& ledger);
// Runtime text
template <typename S>
auto text(S&& content, Style s = {}) -> RuntimeTextNode<decay_t<S>>;
template <typename S>
auto text(S&& content, Style s, TextWrap w) -> RuntimeTextNode<decay_t<S>>;
// Dynamic node
template <typename F>
auto dyn(F&& fn) -> DynNode<decay_t<F>>;
// Map range
template <std::ranges::range R, typename Proj>
auto map(R&& range, Proj&& proj) -> MapNode<decay_t<R>, decay_t<Proj>>;
// each() — alias for map(), for discoverability
template <std::ranges::range R, typename Proj>
auto each(R&& range, Proj&& proj);
// Spacer/separator/blank (function forms)
constexpr auto spacer() -> SpacerNode;
constexpr auto separator() -> SepNode;
constexpr auto blank() -> BlankNode;
DSL Constants¶
inline constexpr SpacerNode space;
inline constexpr SepNode sep;
inline constexpr VSepNode vsep;
inline constexpr BlankNode blank_;
inline constexpr BorderStyle Round = BorderStyle::Round;
inline constexpr BorderStyle Single = BorderStyle::Single;
inline constexpr BorderStyle Thick = BorderStyle::Bold;
inline constexpr BorderStyle Double = BorderStyle::Double;
Element Types¶
Element¶
struct Element {
std::variant<BoxElement, TextElement, ElementList> inner;
// Implicit constructors from each variant type
Element(BoxElement);
Element(TextElement);
Element(ElementList);
Element build() const; // Returns *this (satisfies Node concept)
};
TextElement¶
struct TextElement {
std::string content;
Style style{};
TextWrap wrap{TextWrap::Wrap};
Size measure(int max_width) const;
std::vector<std::string> format(int max_width) const;
};
BoxElement¶
struct BoxElement {
FlexStyle layout{};
Style style{};
BorderConfig border{};
Overflow overflow{Overflow::Visible};
std::vector<Element> children;
bool has_border() const;
int inner_horizontal() const; // padding + border horizontal
int inner_vertical() const; // padding + border vertical
};
ElementList¶
TextWrap¶
enum class TextWrap {
Wrap, // Word wrap at container width
TruncateEnd, // "Long te..."
TruncateMiddle, // "Lon...xt"
TruncateStart, // "...g text"
NoWrap // Overflow
};
Style System¶
Style¶
struct Style {
std::optional<Color> fg, bg;
bool bold = false, dim = false, italic = false;
bool underline = false, strikethrough = false, inverse = false;
Style with_fg(Color c) const;
Style with_bg(Color c) const;
Style with_bold(bool v = true) const;
Style with_dim(bool v = true) const;
Style with_italic(bool v = true) const;
Style with_underline(bool v = true) const;
Style with_strikethrough(bool v = true) const;
Style with_inverse(bool v = true) const;
Style merge(const Style& other) const;
bool empty() const;
std::string to_sgr() const;
};
Style operator|(const Style& lhs, const Style& rhs); // Merge
Color¶
class Color {
public:
enum class Kind { Named, Indexed, Rgb };
// Named colors (constexpr)
static constexpr Color black();
static constexpr Color red();
static constexpr Color green();
static constexpr Color yellow();
static constexpr Color blue();
static constexpr Color magenta();
static constexpr Color cyan();
static constexpr Color white();
static constexpr Color bright_black(); // gray
static constexpr Color bright_red();
static constexpr Color bright_green();
static constexpr Color bright_yellow();
static constexpr Color bright_blue();
static constexpr Color bright_magenta();
static constexpr Color bright_cyan();
static constexpr Color bright_white();
static constexpr Color gray();
// RGB (constexpr)
static constexpr Color rgb(uint8_t r, uint8_t g, uint8_t b);
// Hex (consteval — compile-time only)
static consteval Color hex(uint32_t rgb);
// HSL (constexpr)
static constexpr Color hsl(float h, float s, float l);
// Indexed (256-color)
static Color indexed(uint8_t index);
// Accessors
Kind kind() const;
uint8_t r() const, g() const, b() const;
uint8_t index() const;
// Adjustment (constexpr)
Color lighten(float amount) const;
Color darken(float amount) const;
// SGR sequences
std::string fg_sgr() const;
std::string bg_sgr() const;
};
Theme¶
struct Theme {
Color primary, secondary, accent;
Color success, error, warning, info;
Color text, inverse_text, muted;
Color surface, background, border;
Color diff_added, diff_removed, diff_changed;
Color highlight, selection, cursor, link;
Color placeholder, shadow, overlay;
static constexpr Theme derive(Theme base, auto&& patch);
};
namespace theme {
inline constexpr Theme dark;
inline constexpr Theme light;
inline constexpr Theme dark_ansi;
inline constexpr Theme light_ansi;
}
Border¶
BorderStyle¶
enum class BorderStyle {
None, Single, Double, Round, Bold,
SingleDouble, DoubleSingle, Classic, Arrow
};
BorderSides¶
struct BorderSides {
bool top = false, right = false, bottom = false, left = false;
static BorderSides all();
static BorderSides none();
static BorderSides horizontal(); // top + bottom
static BorderSides vertical(); // left + right
};
BorderText¶
struct BorderText {
std::string content;
BorderTextPos position = BorderTextPos::Top;
BorderTextAlign align = BorderTextAlign::Start;
int offset = 0;
};
BorderColors¶
struct BorderColors {
std::optional<Color> top, right, bottom, left;
static BorderColors uniform(Color c);
};
BorderConfig¶
struct BorderConfig {
BorderStyle style = BorderStyle::None;
BorderSides sides{};
BorderColors colors{};
std::optional<BorderText> text;
bool empty() const;
};
Layout Types¶
FlexDirection¶
FlexWrap¶
Align¶
Justify¶
Overflow¶
Dimension¶
struct Dimension {
enum class Kind { Auto, Fixed, Percent };
Kind kind;
float value;
static Dimension auto_();
static Dimension fixed(int v);
static Dimension percent(float v);
bool is_auto() const;
bool is_fixed() const;
bool is_percent() const;
int resolve(int parent) const;
};
Dimension operator""_pct(unsigned long long v); // 50_pct
FlexStyle¶
struct FlexStyle {
FlexDirection direction = FlexDirection::Row;
FlexWrap wrap = FlexWrap::NoWrap;
Align align_items = Align::Stretch;
Align align_self = Align::Auto;
Justify justify = Justify::Start;
float grow = 0;
float shrink = 1;
Dimension basis = Dimension::auto_();
Dimension width = Dimension::auto_();
Dimension height = Dimension::auto_();
Dimension min_width = Dimension::auto_();
Dimension min_height = Dimension::auto_();
Dimension max_width = Dimension::auto_();
Dimension max_height = Dimension::auto_();
int gap = 0;
Edges<int> padding{};
Edges<int> margin{};
};
Edges\<T>¶
template <typename T>
struct Edges {
T top{}, right{}, bottom{}, left{};
Edges() = default;
Edges(T all); // uniform
Edges(T v, T h); // vertical, horizontal
Edges(T t, T r, T b, T l);
T horizontal() const; // left + right
T vertical() const; // top + bottom
};
Event System¶
Event¶
KeyEvent¶
using Key = std::variant<CharKey, SpecialKey>;
struct CharKey { char32_t codepoint; };
enum class SpecialKey {
Up, Down, Left, Right, Home, End,
PageUp, PageDown, Tab, BackTab,
Backspace, Delete, Insert, Enter, Escape,
F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12
};
struct Modifiers {
bool ctrl = false, alt = false, shift = false, super_ = false;
bool none() const;
};
struct KeyEvent {
Key key;
Modifiers mods;
std::string raw_sequence;
};
MouseEvent¶
enum class MouseButton { Left, Right, Middle, ScrollUp, ScrollDown, None };
enum class MouseEventKind { Press, Release, Move };
struct MouseEvent {
MouseButton button;
MouseEventKind kind;
Columns x;
Rows y;
Modifiers mods;
};
Other Events¶
struct PasteEvent { std::string content; };
struct FocusEvent { bool focused; };
struct ResizeEvent { Columns width; Rows height; };
Event Predicates¶
// Keyboard
bool key(const Event&, char c);
bool key(const Event&, char32_t cp);
bool key(const Event&, SpecialKey sk);
bool ctrl(const Event&, char c);
bool alt(const Event&, char c);
bool shift(const Event&, SpecialKey sk);
bool any_key(const Event&);
const KeyEvent* as_key(const Event&);
// Mouse
struct MousePos { int col, row; };
bool mouse_clicked(const Event&, MouseButton = MouseButton::Left);
bool mouse_released(const Event&, MouseButton = MouseButton::Left);
bool mouse_moved(const Event&);
bool scrolled_up(const Event&);
bool scrolled_down(const Event&);
std::optional<MousePos> mouse_pos(const Event&);
const MouseEvent* as_mouse(const Event&);
// Other
bool resized(const Event&, int* w = nullptr, int* h = nullptr);
bool pasted(const Event&, std::string* out = nullptr);
bool focused(const Event&);
bool unfocused(const Event&);
// Fire-and-forget
template <typename F> bool on(const Event&, char c, F&& fn);
template <typename F> bool on(const Event&, char c1, char c2, F&& fn);
template <typename F> bool on(const Event&, SpecialKey sk, F&& fn);
Signals¶
Signal\<T>¶
template <typename T>
class Signal {
Signal(); // Default-construct T
explicit Signal(U&& initial); // Construct from value
const T& get() const; // Read (auto-tracks dependencies)
const T& operator()() const; // Shorthand for get()
void set(const T& v); // Write (notifies if changed)
void set(T&& v); // Write (move)
void update(F&& fn); // Mutate in-place (always notifies)
auto map(F&& fn) const -> Computed<R>; // Derive computed value
uint64_t version() const; // Change counter
};
Computed\<T>¶
template <typename T>
class Computed {
const T& get() const; // Read (recomputes if dirty)
const T& operator()() const;
};
template <std::invocable F>
auto computed(F&& fn) -> Computed<invoke_result_t<F>>;
Effect¶
class Effect {
Effect(); // Default (inactive)
explicit Effect(F&& fn); // Create and run immediately
void dispose(); // Unsubscribe from all deps
bool active() const;
};
template <std::invocable F>
Effect effect(F&& fn);
Batch¶
class Batch {
Batch(); // Begin batch
~Batch(); // End batch, flush notifications
};
template <std::invocable F>
decltype(auto) batch(F&& fn); // Run fn inside a batch scope
Canvas¶
Canvas¶
class Canvas {
Canvas(int width, int height, StylePool* pool);
void set(int x, int y, char32_t ch, uint16_t style_id, uint8_t width = 0);
void write_text(int x, int y, std::string_view text, uint16_t style_id);
void fill(Rect region, char32_t ch, uint16_t style_id);
void clear();
void resize(int w, int h);
Cell get(int x, int y) const;
int width() const;
int height() const;
void push_clip(Rect clip);
void pop_clip();
};
Cell¶
struct Cell {
char32_t character;
uint16_t style_id;
uint16_t hyperlink_id;
uint8_t width;
uint64_t pack() const;
static Cell unpack(uint64_t v);
};
StylePool¶
class StylePool {
uint16_t intern(const Style& s);
const Style& get(uint16_t id) const;
void clear();
std::size_t size() const;
};
render_tree()¶
Widgets¶
All widgets live in maya::widget. Full documentation in 13-widgets.md.
Input¶
| Widget | Header | Description |
|---|---|---|
Input |
widget/input.hpp |
Single-line text input with cursor and history |
TextArea |
widget/textarea.hpp |
Multi-line text editor |
Checkbox |
widget/checkbox.hpp |
Toggle checkbox |
ToggleSwitch |
widget/checkbox.hpp |
iOS-style toggle switch |
Radio |
widget/radio.hpp |
Radio button group |
Select |
widget/select.hpp |
Dropdown select menu |
Slider |
widget/slider.hpp |
Numeric slider |
Button |
widget/button.hpp |
Clickable button with variants |
CommandPalette |
widget/command_palette.hpp |
Fuzzy-search command launcher |
Data Display¶
| Widget | Header | Description |
|---|---|---|
Table |
widget/table.hpp |
Tabular data with column alignment |
Tree |
widget/tree.hpp |
Expandable tree view |
List |
widget/list.hpp |
Selectable item list |
KeyHelp |
widget/key_help.hpp |
Keyboard shortcut legend |
Badge |
widget/badge.hpp |
Inline status badge |
Callout |
widget/callout.hpp |
Info/success/warning/error callout box |
Link |
widget/link.hpp |
Hyperlink element |
KeyHelp |
widget/key_help.hpp |
Keyboard shortcut legend |
ShortcutRow |
widget/shortcut_row.hpp |
Width-adaptive keyboard hint row (Helix/k9s style) |
ModelBadge |
widget/model_badge.hpp |
Color-coded active-model indicator |
Navigation¶
| Widget | Header | Description |
|---|---|---|
Tabs |
widget/tabs.hpp |
Tab bar navigation |
Breadcrumb |
widget/breadcrumb.hpp |
Breadcrumb path navigation |
Menu |
widget/menu.hpp |
Menu with selectable items |
ActivityBar |
widget/activity_bar.hpp |
Vertical icon sidebar |
Scrollable |
widget/scrollable.hpp |
Scrollable content region |
Scrollbar |
widget/scrollbar.hpp |
Visual indicator for a ScrollState |
Picker |
widget/picker.hpp |
Bordered modal picker with scrollable results |
CommandPalette |
widget/command_palette.hpp |
Fuzzy-search command launcher |
Display¶
| Widget | Header | Description |
|---|---|---|
StreamingMarkdown |
widget/markdown.hpp |
Streaming markdown renderer |
Spinner |
widget/spinner.hpp |
Animated loading spinner |
ProgressBar |
widget/progress.hpp |
Progress bar with percentage |
Gauge |
widget/gauge.hpp |
Gauge / meter display |
Divider |
widget/divider.hpp |
Horizontal or vertical divider |
Image |
widget/image.hpp |
Terminal image display |
gradient() |
widget/gradient.hpp |
Color gradient text builder |
Disclosure |
widget/disclosure.hpp |
Collapsible disclosure section |
Html |
widget/html.hpp |
Render a safe subset of HTML as styled Elements |
Overlay |
widget/overlay.hpp |
Base layer + one anchored floating element |
Overlay¶
| Widget | Header | Description |
|---|---|---|
Modal |
widget/modal.hpp |
Modal dialog with buttons |
Popup |
widget/popup.hpp |
Floating popup |
ToastManager |
widget/toast.hpp |
Toast notification manager |
Visualization¶
| Widget | Header | Description |
|---|---|---|
BarChart |
widget/bar_chart.hpp |
Horizontal/vertical bar chart |
LineChart |
widget/line_chart.hpp |
Line chart with series |
Sparkline |
widget/sparkline.hpp |
Inline sparkline graph |
Heatmap |
widget/heatmap.hpp |
Grid heatmap |
Calendar |
widget/calendar.hpp |
Calendar date display |
PixelCanvas |
widget/canvas.hpp |
Pixel-level drawing canvas |
FlameChart |
widget/flame_chart.hpp |
Flame graph for nested execution spans |
Waterfall |
widget/waterfall.hpp |
Timing waterfall chart (devtools style) |
Timeline |
widget/timeline.hpp |
Vertical CI/pipeline event timeline |
GitGraph |
widget/git_graph.hpp |
Commit graph with colored branch lines |
Agent UI¶
Composable pieces of a Claude-Code / Zed-style agent conversation. Thread
is the top-level viewport; the rest are the parts it (or a host) assembles.
| Widget | Header | Description |
|---|---|---|
Thread |
widget/thread.hpp |
Top-level viewport: empty → WelcomeScreen, else Conversation |
WelcomeScreen |
widget/welcome_screen.hpp |
Empty-thread brand splash + starters/hints |
Conversation |
widget/conversation.hpp |
Vertical list of turns with dividers + in-flight indicator |
Turn |
widget/turn.hpp |
One speaker turn (rail, role, checkpoint) |
TurnDivider |
widget/turn_divider.hpp |
Styled rule between conversation turns |
CheckpointDivider |
widget/checkpoint_divider.hpp |
Full-width "↺ Restore checkpoint" rule above a turn |
Composer |
widget/composer.hpp |
State-driven bordered input box (idle/streaming/permission) |
AgentTimeline |
widget/agent_timeline.hpp |
Bordered Actions panel logging tool events for a turn |
ToolBodyPreview |
widget/tool_body_preview.hpp |
Per-ToolKind body detail under a timeline event |
AppLayout |
widget/app_layout.hpp |
Top-level chat-app frame (header/body/composer/overlay) |
UserMessage |
widget/message.hpp |
Chat user message bubble |
AssistantMessage |
widget/message.hpp |
Chat assistant message bubble |
ThinkingBlock |
widget/thinking.hpp |
Collapsible AI thinking block |
StreamingCursor |
widget/streaming_cursor.hpp |
Pulsing "assistant is streaming" indicator |
SystemBanner |
widget/system_banner.hpp |
Severity-coloured system alert (ctx warning, rate limit) |
TodoList |
widget/todo_list.hpp |
Session todo list card |
PlanView |
widget/plan_view.hpp |
Task plan with status tracking |
Permission |
widget/permission.hpp |
Permission approval prompt |
Session / Diagnostics¶
| Widget | Header | Description |
|---|---|---|
DiffView |
widget/diff_view.hpp |
Side-by-side or unified diff |
InlineDiff |
widget/inline_diff.hpp |
Two-line word-level LCS diff |
FileChanges |
widget/file_changes.hpp |
Session file-change summary (created/modified/deleted + counts) |
ChangesStrip |
widget/changes_strip.hpp |
Bordered "session has pending changes" banner |
FileRef |
widget/file_ref.hpp |
File reference with icon |
LogViewer |
widget/log_viewer.hpp |
Filterable log viewer |
SearchResult |
widget/search_result.hpp |
Grouped search results display |
ErrorBlock |
widget/error_block.hpp |
Structured error/exception card |
GitStatus |
widget/git_status.hpp |
Branch + working-tree status |
ContextWindow |
widget/context_window.hpp |
Segmented context-window usage meter |
TokenStream |
widget/token_stream.hpp |
Live token-rate sparkline + stats (compact/full) |
CostTracker |
widget/cost_tracker.hpp |
Per-turn + cumulative token/cost breakdown |
ApiUsage |
widget/api_usage.hpp |
API rate-limit / request-count / latency display |
ActivityIndicator |
widget/activity_indicator.hpp |
Single-row hex-dump activity tape |
Status Bar¶
| Widget | Header | Description |
|---|---|---|
StatusBar |
widget/status_bar.hpp |
Single-line streaming status bar (composes the pieces below) |
TokenStreamSparkline |
widget/token_stream_sparkline.hpp |
Live tok/s rate + sparkline chip (adaptive width) |
PhaseChip |
widget/phase_chip.hpp |
Current-phase verb + elapsed, breathing |
TitleChip |
widget/title_chip.hpp |
Breadcrumb / title chip |
ContextGauge |
widget/context_gauge.hpp |
Context-window usage gauge |
PhaseAccent |
widget/phase_accent.hpp |
Top/bottom accent rail strip |
StatusBanner |
widget/status_banner.hpp |
Full-width toast that takes over the activity row |
Tool Widgets¶
| Widget | Header | Description |
|---|---|---|
ToolCall |
widget/tool_call.hpp |
Generic tool invocation display |
BashTool |
widget/bash_tool.hpp |
Shell command tool call |
ReadTool |
widget/read_tool.hpp |
File read tool call |
EditTool |
widget/edit_tool.hpp |
File edit tool call |
WriteTool |
widget/write_tool.hpp |
File write tool call |
FetchTool |
widget/fetch_tool.hpp |
HTTP fetch tool call |
AgentTool |
widget/agent_tool.hpp |
Sub-agent tool call |
GitCommitTool |
widget/git_commit_tool.hpp |
Git commit operation card |
Core Types¶
Strong\<Tag, T>¶
template <typename Tag, typename T>
struct Strong {
T value{};
// Arithmetic: Strong + Strong, Strong - Strong, etc.
// Comparison: ==, !=, <, >, <=, >=
};
Size / Position / Rect¶
using Columns = Strong<ColumnTag, int>;
using Rows = Strong<RowTag, int>;
struct Size { Columns width; Rows height; };
struct Position { Columns x; Rows y; };
struct Rect { Position pos; Size size; };
Result / Status / Error¶
enum class ErrorKind {
TerminalInit, Io, LayoutOverflow, InvalidStyle,
InvalidUtf8, Unsupported, Signal, WouldBlock
};
struct Error {
ErrorKind kind;
std::string message;
std::source_location location;
static Error terminal(std::string msg);
static Error io(std::string msg);
static Error from_errno(std::string ctx);
};
template <typename T>
using Result = std::expected<T, Error>;
using Status = Result<void>;