feat: implement hx-boost for reliable loading indication

This commit is contained in:
Björn Fromme
2026-03-16 11:59:12 +01:00
parent 602fb31f27
commit 1e107c68b4
32 changed files with 163 additions and 271 deletions
+14 -23
View File
@@ -4,9 +4,14 @@ export default class extends Controller {
static targets = ['indicator']
static classes = ['hidden']
static values = {
visible: {
type: Boolean,
default: false
}
}
connect() {
this.isVisible = false
this.debounceTimeout = null
// Bind event handlers to preserve context
@@ -40,9 +45,9 @@ export default class extends Controller {
}
}
handleBeforeRequest(event) {
handleBeforeRequest() {
// Don't start a new debounce if already visible
if (this.isVisible) {
if (true === this.visibleValue) {
return
}
@@ -52,31 +57,17 @@ export default class extends Controller {
}, 200)
}
handleAfterRequest(event) {
handleAfterRequest() {
// Clear debounce timer if request completes before 200ms
if (this.debounceTimeout) {
clearTimeout(this.debounceTimeout)
this.debounceTimeout = null
}
// Check if response contains HX-Redirect header
const xhr = event.detail.xhr
const hxRedirect = xhr.getResponseHeader('HX-Redirect')
// Keep loading indicator visible if redirecting
if (hxRedirect) {
// Ensure indicator is visible during redirect
if (!this.isVisible) {
this.show()
}
return
}
// Hide indicator if it's visible
this.hide()
}
handleTimeout(event) {
handleTimeout() {
// Hide loading indicator
this.hide()
@@ -86,23 +77,23 @@ export default class extends Controller {
handlePageShow(event) {
// event.persisted is true when page is restored from bfcache (back/forward navigation)
if (event.persisted) {
if (true === event.persisted) {
this.hide()
}
}
handleHistoryRestore(event) {
handleHistoryRestore() {
// HTMX history restore - hide loading indicator
this.hide()
}
show() {
this.isVisible = true
this.visibleValue = true
this.indicatorTarget.classList.remove(this.hiddenClass)
}
hide() {
this.isVisible = false
this.visibleValue = false
this.indicatorTarget.classList.add(this.hiddenClass)
}
}