Elements & render()
mx.div() returns a lightweight description (an array marked with ._=true). When you pass it into render, mx creates or updates DOM nodes efficiently.
let { div, span } = mx;
let host = dom.div();
// Initial render
host.render(
div({ class: "box" }, span("A")),
div({ class: "box" }, span("B"))
);
// Update - re-render the same container, mx patches minimally
host.render(
div({ class: "box" }, span("A (updated)")),
div({ class: "box" }, span("B"))
);
document.body.render(host);Tip
You can render multiple children at once: el.render(head, main, footer). null, undefined, and false are ignored, which makes conditional rendering straightforward.
Attributes & Prefixes
Attributes are passed as the first argument. Use the . prefix to set DOM properties directly:
let { input, button } = mx;
let field = input({
type: "text",
placeholder: "Your name",
".value": "", // .prefix sets DOM property directly
disabled: false, // false/null removes the attribute
required: true // true sets the string "true"
});
let submit = button({ type: "submit" }, "Send");Property vs Attribute
DOM inputs care about the property value, not the attribute value. Use ".value" to set it. Same for .checked and .selectedIndex.
Events (onclick)
Set event handlers as properties in lowercase: onclick, oninput, onchange, etc.
Important
Use lowercase event names. onClick won't work - it's not React. Write onclick.
let { div, button, span } = mx;
let count = 0;
let host = dom.div();
function Counter() {
return div(
button({ onclick() { count--; host.render(Counter()); } }, "−"),
span(" " + count + " "),
button({ onclick() { count++; host.render(Counter()); } }, "+")
);
}
host.render(Counter());
document.body.render(host);Children
Children can be strings, DOM nodes, or other mx.* arrays.
let { ul, li, strong } = mx;
let list = ul(
li("One"),
li(strong("Two")),
li("Three")
);SVG Namespace Inheritance
mx.svg() creates an element in the SVG namespace. Any element rendered inside an SVG parent automatically gets the SVG namespace too - you don't need to mark <g>, <path>, <polyline>, or any other nested SVG element specially:
// All children rendered inside <svg> inherit svgNS automatically
mx.svg({ viewBox: '0 0 100 100' },
mx.g({ transform: 'translate(10, 10)' },
mx.circle({ cx: 40, cy: 40, r: 30, fill: 'red' }),
mx.path({ d: 'M0 0 L80 80' })
)
)The check is based on the host element's namespaceURI. Nested render() calls re-detect namespace from their own host, so deeply nested SVG trees work correctly.
Known limitation: foreignObject
<foreignObject> is itself in the SVG namespace, but its children should be HTML. mx doesn't special-case this - children of foreignObject get SVG namespace, which breaks HTML rendering inside. If you need HTML inside SVG, build the foreignObject contents with raw document.createElement or use a separate dom() call and insert the resulting node.