87 lines
3.1 KiB
Markdown
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
|