Terminal UI library for MoonBit with virtual DOM-based rendering.
- Virtual DOM with diff-based ANSI rendering
- Flexbox and CSS Grid layout (powered by mizchi/crater)
- Reactive signals integration (mizchi/signals)
- Styled UI components (@components)
- Keyboard and mouse input handling
{
"import": {
"mizchi/tui": "0.3.0"
}
}mizchi/tui/
├── vnode/ # Virtual DOM primitives (row, column, view, grid, text)
├── components/ # Styled UI components (button, modal, table, etc.)
├── headless/ # State types (ButtonState, InputState, etc.)
├── events/ # Input parsing (KeyEvent, MouseEvent)
├── render/ # ANSI rendering engine
├── io/ # Platform I/O (terminal size, keypress)
└── core/ # Low-level types (Component, Color)
fn main {
let node = @vnode.column(gap=1.0, padding=1.0, border="rounded", [
@vnode.text("Hello, TUI!", fg="cyan", bold=true),
@components.button("Click me"),
@components.progress_bar(0.7),
])
// Render to string
let output = @vnode.render_vnode_once(80, 24, node)
println(output)
}// Flex containers
@vnode.view([...]) // column by default
@vnode.view(direction="row", [...]) // horizontal
@vnode.row([...]) // shorthand for direction="row"
@vnode.column([...]) // shorthand for direction="column"
// Grid layout
@vnode.grid(columns=[1.0, 2.0, 1.0], [...]) // 1fr 2fr 1fr
@vnode.grid_item(column_span=2, child=...) // span multiple cells
// Named grid areas
@vnode.grid(
areas=["header header", "sidebar main", "footer footer"],
[
@vnode.grid_area("header", header_content),
@vnode.grid_area("sidebar", sidebar_content),
@vnode.grid_area("main", main_content),
@vnode.grid_area("footer", footer_content),
]
)
// Text
@vnode.text("Hello", fg="cyan", bold=true)
// Spacing
@vnode.spacer() // flexible space
@vnode.hspace(2.0) // horizontal space
@vnode.vspace(1.0) // vertical space// Buttons
@components.button("Submit", state=@headless.ButtonState::Focused)
@components.icon_button("✕")
@components.text_button("Learn more")
// Form
@components.checkbox("Remember me", true)
@components.radio("Option A", true)
@components.switch(true, "Dark mode")
@vnode.input("value", placeholder="Enter text...")
// Selection
@components.listbox(items, selected_id)
@components.tab_bar(tabs, selected_id)
@components.combobox_trigger("Select...", open=false)
// Feedback
@components.progress_bar(0.5)
@components.spinner(tick)
@components.gauge("CPU", 0.75)
@components.sparkline(data)
// Modal
@components.modal("Title", [...])
@components.alert_dialog("Error occurred")
@components.confirm_dialog("Delete?")
// Dashboard
@components.table(columns, rows)
@components.stat("Users", "1,234")
@components.meter("Memory", 0.8)The experiments/eval_ui package provides a layout regression harness and
layout-rect snapshots (IDs only, auto/root filtered).
# Base patterns
moon -C experiments/eval_ui run . -- --layout-snapshot
# Persona 5 patterns
moon -C experiments/eval_ui run . -- --layout-snapshot-p5For running eval with layout-rect inference (no AA parsing), add --infer-layout:
moon -C experiments/eval_ui run . -- --infer-layoutSnapshots:
__snapshots__/eval_ui_layout.txt__snapshots__/eval_ui_layout_p5.txt
moon run examples/simple # Minimal counter app
moon run examples/command-launcher # Raycast-style command palette
moon run examples/completion # Inline completion UI
moon run examples/components # Component showcase gallery
moon run examples/editor # Text editor with syntax highlighting
moon run examples/form # Form with inline editing
moon run examples/grid-area # Named grid area layout
moon run examples/grid-layout # Grid layout demo (dashboard/calendar)
moon run examples/kitty-graphics # Kitty terminal graphics protocol demo
moon run examples/roguelike # Roguelike game UI
moon run examples/wizard # Multi-step setup wizard (inquirer.js-style)Note: The chat example moved to mizchi/vivebox.
See docs/tutorial.mbt.md for detailed API documentation.
MIT
