Hyper · htmx-style

Confirmations & loading indicators

One attribute asks "Are you sure?"; another shows a spinner while the request runs. The requesting element gets aria-busy="true" for free.

kj-confirm="Delete invoice #1001?" shows the browser's native confirm dialog and cancels the request if the user declines. kj-indicator="#spinner" shows the named element for the duration of the request and hides it afterwards.

While a request is in flight the element carries aria-busy="true", which assistive technology understands and which you can style: [aria-busy="true"] { opacity: .6; cursor: progress; }.

Live · Safe deletes and a slow report

InvoiceAmountActions
#1001$420
#1002$1,280
#1003$96
Working…

Zero JavaScript. items.php answers DELETE with an empty body, so outerHTML removes the row.

View the source for this demo
HTML
<div class="table-wrap" style="margin-top:0"><table class="inv">
  <thead><tr><th scope="col">Invoice</th><th scope="col">Amount</th><th scope="col"><span class="sr-only">Actions</span></th></tr></thead>
  <tbody>
    <tr id="inv-1"><td>#1001</td><td>$420</td><td><button type="button" kj-delete="/api/items.php?id=1" kj-target="#inv-1" kj-swap="outerHTML" kj-confirm="Delete invoice #1001?">Delete</button></td></tr>
    <tr id="inv-2"><td>#1002</td><td>$1,280</td><td><button type="button" kj-delete="/api/items.php?id=2" kj-target="#inv-2" kj-swap="outerHTML" kj-confirm="Delete invoice #1002?">Delete</button></td></tr>
    <tr id="inv-3"><td>#1003</td><td>$96</td><td><button type="button" kj-delete="/api/items.php?id=3" kj-target="#inv-3" kj-swap="outerHTML" kj-confirm="Delete invoice #1003?">Delete</button></td></tr>
  </tbody>
</table></div>
<div class="row" style="margin-top:14px">
  <button type="button" kj-get="/api/slow.php?ms=1600" kj-target="#report" kj-indicator="#report-spin">Run report (1.6 s)</button>
  <div class="spin" id="report-spin" role="status">Working…</div>
</div>
<div id="report" aria-live="polite" style="margin-top:10px"></div>

More examples

Markup

HTML
<button kj-delete="/api/account" kj-confirm="This cannot be undone. Continue?">Delete account</button>
<button kj-post="/export" kj-indicator="#export-spin">Export CSV</button>
<span id="export-spin" hidden>Preparing…</span>

API

kj-confirm="message"

Show a native confirm dialog before requesting.

Reference: kj-confirm →
kj-indicator="#selector"

Element to show while the request is in flight (the trigger also gets aria-busy="true").

Reference: kj-indicator →

Migrating

Coming from htmxhx-confirm → kj-confirm. jsKjs shows/hides the indicator element itself rather than toggling an htmx-request class; hx-disabled-elt is not included.

Related features