A modern, component-based UI framework for Minetest and Luanti, inspired by React and virtual DOM patterns.
Build complex, dynamic formspec UIs in plain Lua with composable components, state hooks, event handlers, and efficient re-rendering.
- createElement(type, props, ...children):
Construct a virtual UI tree (VNode/fiber) from components and primitives. - Component Functions:
Write reusable components as plain Lua functions—return other components or widgets. - Hooks:
UseuseState,useEffect, and friends to manage state, timers, and side effects—per player/form. - Efficient Rendering:
Diff old/new trees; only update changed formspec lines.
Schedules UI updates in sync with game ticks for performance. - Event System:
Register event handlers (e.g.,onClick,onChange); wire them through formspec fields with minimal boilerplate. - Custom Widgets:
Compose simple building blocks (e.g.,Slot,ProgressBar,Tabs) into advanced UIs. - Robustness:
Error boundaries, keyed lists, debug logging, and hooks to support robust, testable UI code. - Full Logging:
Log every significant action for easy debugging and learning.
local ui = require("ui") -- Or _G.ui for quick scripts
local Furnace = function(props)
local state, setState = ui.useState("idle")
ui.useEffect(function()
-- Poll world state or schedule periodic UI updates
end, { /* dependencies */ })
return ui.hbox({ align = "center", spacing = 0.3 }, {
ui.vbox({}, {
ui.label("Input"),
ui.item_image(props.input)
}),
ui.vbox({}, {
ui.label("Fuel"),
ui.item_image(props.fuel)
}),
ui.vbox({}, {
ui.label("Output"),
ui.item_image(props.output)
}),
ui.ProgressBar({ progress = props.progress })
})
end
minetest.register_chatcommand("furnaceui", {
description = "Show demo UI",
func = function(name)
ui.render(name, ui.createElement(Furnace, {
input = "default:iron_lump",
fuel = "default:coal_lump",
output = "default:steel_ingot",
progress = 0.5
}))
end
})