lernschiff/docs/superpowers/specs/2026-05-22-button-spinner-o...

3.1 KiB

Button Spinner Overlay — Design

Datum: 2026-05-22 Scope: Auth-Page Buttons (Login, Confirm-Password, Forgot-Password, Reset-Password, Verify-Email)

Problem

Aktuelles Loading-Pattern der Auth-Buttons:

  • Text + Icon werden via wire:loading.remove ausgeblendet
  • Spinner + "Wird geladen…"-Text werden via wire:loading eingeblendet
  • Button-Größe ist stabil, aber UX wirkt unruhig (Text wechselt komplett)
  • Spinner steht links neben Loading-Text, nicht zentriert

Anforderungen

  1. Spinner zentriert als Overlay über dem Button-Inhalt
  2. Button-Größe stabil beim Wechsel Loading/Idle
  3. Text bekommt opacity-50 beim Laden, damit Spinner besser sichtbar ist
  4. Konsistentes Pattern über alle Auth-Buttons

Lösungsansatz

relative/absolute Positionierung — Text bleibt im Document-Flow, Spinner wird darüber gelegt.

Markup-Pattern

<x-primary-button class="w-full relative" wire:loading.attr="disabled">
    <!-- Text-Layer: immer sichtbar, dimmt beim Laden -->
    <span wire:loading.class="opacity-50"
          wire:target="<method>"
          class="flex items-center gap-2 transition-opacity">
        <x-heroicon-o-... class="w-4 h-4" />
        Button-Text
    </span>

    <!-- Spinner-Layer: absolute overlay, nur beim Laden sichtbar -->
    <span wire:loading
          wire:target="<method>"
          class="absolute inset-0 flex items-center justify-center">
        <svg class="animate-spin w-4 h-4 text-white" ...>
            <!-- Spinner-Path -->
        </svg>
    </span>
</x-primary-button>

Key-Mechanismen

Aspekt Implementierung
Button-Größe stabil Text-Span bleibt immer im Flow (kein display:none)
Spinner zentriert absolute inset-0 flex items-center justify-center
Text dimmt wire:loading.class="opacity-50" + transition-opacity
Spinner über Text absolute positioniert auf relative Button
Disabled-State wire:loading.attr="disabled" (unverändert)

Scope — 5 Dateien

Datei Aktion
livewire/pages/auth/login.blade.php Pattern umbauen
livewire/pages/auth/confirm-password.blade.php Pattern umbauen
livewire/pages/auth/forgot-password.blade.php Pattern umbauen
livewire/pages/auth/reset-password.blade.php Pattern umbauen
livewire/pages/auth/verify-email.blade.php Spinner neu hinzufügen (gleiches Pattern)

primary-button.blade.php bleibt unverändert (Slot-basiert).

Nicht im Scope

  • Andere Buttons im Codebase (z.B. Dashboard, Settings) — nur Auth-Pages
  • Änderungen an primary-button.blade.php selbst — Pattern wird per Page erstellt
  • Backend-Logic, Routes, Auth-Flow — reine UI-Änderung

Testing

  • Bestehende 46 Tests (Pest) laufen unverändert durch
  • Keine neuen Tests nötig (UI-only)
  • Manuelle Verifikation: Login-Button im Browser, Submit auslösen, Spinner-Position prüfen

Verifikation nach Implementation

  1. Curl: Login-HTML enthält relative + absolute inset-0 Klassen
  2. Browser: Spinner mittig sichtbar beim Submit, Text dimmt, Button springt nicht
  3. php artisan test: 46 passed