Nexanexa
← Referencia

@nexa/ui — Interactivos, sin isla

Estado real en cliente — pero ninguno necesita una isla: activación progresiva de siempre.

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) — foco atrapado, Escape cierra, devuelve el foco al elemento anterior. ui está siempre disponible, no hace falta declararlo en [imports].

Apilamiento de Dialog

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

Abrir un Dialog mientras otro ya está abierto lo apila encima (z-index correcto) y oculta el de abajo de lectores de pantalla (aria-hidden) mientras esté cubierto.

ui.confirm() / ui.alert()

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

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

Confirmar antes de una acción destructiva, o avisar que algo se guardó, sin escribir el <div class="nx-dialog"> a mano. Escape en confirm() cuenta como cancelar; en alert(), como aceptar.

Drawer

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

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

Mismo contrato de accesibilidad que Dialog, pensado para sidebars/menús laterales en vez de una caja centrada.

Toast / snackbar

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

ui.notify() — no confundir con platform.notify() (notificación real del sistema operativo): esta es efímera, dentro de la página. Se apila con otras, se auto-cierra a los 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) lee de qué botón vino el click y su data-tab, encuentra el .nx-tab-group más cercano, y hace el resto.

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). Con data-exclusive="true" en el contenedor, abrir un item cierra los demás.

Ordenar y filtrar una 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) ordena por la columna del <th> clickeado (numérico si ambas celdas lo son). ui.filterTable(table, query) oculta filas cuyo texto no matchea. Ambos client-side, sin re-pedir nada al backend.