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

87 lines
3.1 KiB
Markdown

# 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
```html
<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