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 empty attribute
});

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")
);