Nexanexa
← Reference

@nexa/ui — Interactive, no island

Real client-side state — but none of these need an island: the usual progressive activation.

Dialog

function open() { ui.openDialog(document.querySelector(".nx-dialog")); }
function close() { ui.closeDialog(document.querySelector(".nx-dialog")); }

<button onClick={open}>Abrir</button>
<div class="nx-dialog" hidden>
    <p>Contenido</p>
    <button onClick={close}>Cerrar</button>
</div>

ui.openDialog(el)/ui.closeDialog(el) — trapped focus, Escape closes it, returns focus to the previous element. ui is always available, nothing to declare in [imports].

Dialog stacking

// abrir un segundo Dialog desde dentro del primero ya abierto:
// se apila sobre él sin romper ninguno de los dos

Opening a Dialog while another is already open stacks it on top (correct z-index) and hides the one below from screen readers (aria-hidden) while it's covered.

ui.confirm() / ui.alert()

async function removeItem() {
    if (await ui.confirm("¿Seguro que querés borrar esto?")) {
        // borrar
    }
}

await ui.alert("Guardado con éxito");

Confirm before a destructive action, or notify that something was saved, without writing the <div class="nx-dialog"> by hand. Escape in confirm() counts as canceling; in alert(), as accepting.

Drawer

function openMenu() { ui.openDrawer(document.querySelector(".nx-drawer")); }

<button onClick={openMenu}>Menú</button>
<div class="nx-drawer" hidden>
    <a href="/">Inicio</a>
</div>

Same accessibility contract as Dialog, meant for sidebars/side menus instead of a centered box.

Toast / snackbar

function saveOk() {
    ui.notify({ message: "Guardado con éxito", variant: "success" });
}

ui.notify() — not to be confused with platform.notify() (a real OS notification): this one is ephemeral, inside the page. It stacks with others, auto-closes after 4s.

Tabs

function selectTab(event) { ui.selectTab(event); }

<div class="nx-tab-group">
    <div class="nx-tab-list" role="tablist">
        <button class="nx-tab" data-tab="uno" aria-selected="true" onClick={selectTab}>Uno</button>
        <button class="nx-tab" data-tab="dos" onClick={selectTab}>Dos</button>
    </div>
    <div class="nx-tab-panel" data-tab="uno">Contenido uno</div>
    <div class="nx-tab-panel" data-tab="dos" hidden>Contenido dos</div>
</div>

ui.selectTab(event) reads which button was clicked and its data-tab, finds the nearest .nx-tab-group, and does the rest.

Accordion

function toggle(event) { ui.toggleAccordionItem(event); }

<div class="nx-accordion">
    <div class="nx-accordion-item">
        <button class="nx-accordion-trigger" aria-expanded="false" onClick={toggle}>Pregunta</button>
        <div class="nx-accordion-panel" hidden>Respuesta</div>
    </div>
</div>

ui.toggleAccordionItem(event). With data-exclusive="true" on the container, opening one item closes the rest.

Sorting and filtering a Table

function sortByColumn(event) { ui.sortTable(event); }
function filterOrders(event) { ui.filterTable(document.getElementById("orders"), event.target.value); }

<input type="search" onInput={filterOrders} />
<table id="orders" class="nx-table">
    <thead><tr><th data-sortable onClick={sortByColumn}>Cliente</th></tr></thead>
    <tbody>...</tbody>
</table>

ui.sortTable(event) sorts by the clicked <th>'s column (numeric if both cells are). ui.filterTable(table, query) hides rows whose text doesn't match. Both client-side, no re-fetch.