perf: add loading indicators to storage modal buttons for better UX

This commit is contained in:
2026-01-24 20:48:08 -05:00
parent df28e742ed
commit 3192235ffa

View File

@@ -149,8 +149,11 @@
</button>
@if($this->remainingStorage > 0 && !$vmRunning)
<button wire:click="openAddDriveModal"
wire:loading.attr="disabled"
wire:loading.class="opacity-75"
class="inline-flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-lg bg-primary text-white hover:bg-primary/90 transition-colors">
<x-ri-add-line class="size-4" />
<x-ri-loader-4-line class="size-4 animate-spin" wire:loading wire:target="openAddDriveModal" />
<x-ri-add-line class="size-4" wire:loading.remove wire:target="openAddDriveModal" />
Add Drive
</button>
@elseif($this->remainingStorage > 0 && $vmRunning)
@@ -344,13 +347,19 @@
</button>
@else
<button wire:click="openEditDriveModal('{{ $driveKey }}')"
wire:loading.attr="disabled"
wire:target="openEditDriveModal('{{ $driveKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-neutral bg-background hover:bg-background-secondary transition-colors">
<x-ri-settings-3-line class="size-3.5" />
<x-ri-loader-4-line class="size-3.5 animate-spin" wire:loading wire:target="openEditDriveModal('{{ $driveKey }}')" />
<x-ri-settings-3-line class="size-3.5" wire:loading.remove wire:target="openEditDriveModal('{{ $driveKey }}')" />
Settings
</button>
<button wire:click="openMoveDriveModal('{{ $driveKey }}')"
wire:loading.attr="disabled"
wire:target="openMoveDriveModal('{{ $driveKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-neutral bg-background hover:bg-background-secondary transition-colors">
<x-ri-arrow-left-right-line class="size-3.5" />
<x-ri-loader-4-line class="size-3.5 animate-spin" wire:loading wire:target="openMoveDriveModal('{{ $driveKey }}')" />
<x-ri-arrow-left-right-line class="size-3.5" wire:loading.remove wire:target="openMoveDriveModal('{{ $driveKey }}')" />
Device Bus
</button>
@if(count($unusedDrives) >= 2)
@@ -362,16 +371,22 @@
</button>
@else
<button wire:click="openDetachModal('{{ $driveKey }}')"
wire:loading.attr="disabled"
wire:target="openDetachModal('{{ $driveKey }}')"
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(234 179 8 / 0.5); background-color: rgb(234 179 8 / 0.1); color: rgb(234 179 8); transition: background-color 0.15s ease;"
onmouseover="this.style.backgroundColor='rgb(234 179 8 / 0.2)'"
onmouseout="this.style.backgroundColor='rgb(234 179 8 / 0.1)'">
<x-ri-eject-line class="size-3.5" />
<x-ri-loader-4-line class="size-3.5 animate-spin" wire:loading wire:target="openDetachModal('{{ $driveKey }}')" />
<x-ri-eject-line class="size-3.5" wire:loading.remove wire:target="openDetachModal('{{ $driveKey }}')" />
Detach
</button>
@endif
<button wire:click="openDeleteModal('{{ $driveKey }}')"
wire:loading.attr="disabled"
wire:target="openDeleteModal('{{ $driveKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-danger/50 bg-danger/10 text-danger hover:bg-danger/20 transition-colors">
<x-ri-delete-bin-line class="size-3.5" />
<x-ri-loader-4-line class="size-3.5 animate-spin" wire:loading wire:target="openDeleteModal('{{ $driveKey }}')" />
<x-ri-delete-bin-line class="size-3.5" wire:loading.remove wire:target="openDeleteModal('{{ $driveKey }}')" />
Delete
</button>
@endif
@@ -463,24 +478,33 @@
</button>
<button wire:click="deleteUnusedDrive('{{ $unusedKey }}')"
wire:confirm="Are you sure you want to permanently delete this detached drive? This action cannot be undone."
wire:loading.attr="disabled"
wire:target="deleteUnusedDrive('{{ $unusedKey }}')"
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(239 68 68 / 0.5); background-color: rgb(239 68 68 / 0.1); color: rgb(239 68 68); transition: background-color 0.15s ease;"
onmouseover="this.style.backgroundColor='rgb(239 68 68 / 0.2)'"
onmouseout="this.style.backgroundColor='rgb(239 68 68 / 0.1)'">
<x-ri-delete-bin-line class="size-3.5" />
<span wire:loading wire:target="deleteUnusedDrive('{{ $unusedKey }}')" class="size-3.5 border-2 border-current border-r-transparent rounded-full animate-spin"></span>
<x-ri-delete-bin-line wire:loading.remove wire:target="deleteUnusedDrive('{{ $unusedKey }}')" class="size-3.5" />
Delete
</button>
@else
<button wire:click="openReattachModal('{{ $unusedKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-success/50 bg-success/10 text-success hover:bg-success/20 transition-colors">
<x-ri-link class="size-3.5" />
wire:loading.attr="disabled"
wire:target="openReattachModal('{{ $unusedKey }}')"
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-xs font-medium rounded-lg border border-success/50 bg-success/10 text-success hover:bg-success/20 transition-colors disabled:opacity-50 disabled:cursor-not-allowed">
<span wire:loading wire:target="openReattachModal('{{ $unusedKey }}')" class="size-3.5 border-2 border-current border-r-transparent rounded-full animate-spin"></span>
<x-ri-link wire:loading.remove wire:target="openReattachModal('{{ $unusedKey }}')" class="size-3.5" />
Reattach
</button>
<button wire:click="deleteUnusedDrive('{{ $unusedKey }}')"
wire:confirm="Are you sure you want to permanently delete this detached drive? This action cannot be undone."
wire:loading.attr="disabled"
wire:target="deleteUnusedDrive('{{ $unusedKey }}')"
style="display: inline-flex; align-items: center; gap: 0.375rem; padding: 0.375rem 0.75rem; font-size: 0.75rem; font-weight: 500; border-radius: 0.5rem; border: 1px solid rgb(239 68 68 / 0.5); background-color: rgb(239 68 68 / 0.1); color: rgb(239 68 68); transition: background-color 0.15s ease;"
onmouseover="this.style.backgroundColor='rgb(239 68 68 / 0.2)'"
onmouseout="this.style.backgroundColor='rgb(239 68 68 / 0.1)'">
<x-ri-delete-bin-line class="size-3.5" />
<span wire:loading wire:target="deleteUnusedDrive('{{ $unusedKey }}')" class="size-3.5 border-2 border-current border-r-transparent rounded-full animate-spin"></span>
<x-ri-delete-bin-line wire:loading.remove wire:target="deleteUnusedDrive('{{ $unusedKey }}')" class="size-3.5" />
Delete
</button>
@endif