- TallStackUI 4 (MIT) statt Flux; Komponenten mit Präfix ts- (<x-ts-…>) - Layouts, Login-, Passwort-, 2FA- und Einstellungsseiten neu aufgebaut - Livewire-Skripte explizit in beiden Layouts, damit Alpine auch auf den Fortify-Seiten ohne Livewire-Komponente läuft - Dark Mode über tallstackui_darkTheme(), ohne Aufblitzen beim Laden - Registrierungs-View und ungenutzte Layout-Varianten entfernt - Test: Seiten laden keine Ressourcen von fremden Hosts (Vorgabe "alles lokal") Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
72 lines
3.1 KiB
PHP
72 lines
3.1 KiB
PHP
<div class="space-y-6 rounded-xl border border-gray-200 py-6 shadow-sm dark:border-dark-600"
|
|
wire:cloak
|
|
x-data="{ showRecoveryCodes: false }">
|
|
<div class="space-y-2 px-6">
|
|
<div class="flex items-center gap-2">
|
|
<x-ts-icon name="lock-closed" sm />
|
|
<x-heading level="3" size="lg">{{ __('2FA recovery codes') }}</x-heading>
|
|
</div>
|
|
<x-subheading>
|
|
{{ __('Recovery codes let you regain access if you lose your 2FA device. Store them in a secure password manager.') }}
|
|
</x-subheading>
|
|
</div>
|
|
|
|
<div class="px-6">
|
|
<div class="flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
|
<x-ts-button x-show="!showRecoveryCodes"
|
|
icon="eye"
|
|
x-on:click="showRecoveryCodes = true"
|
|
aria-expanded="false"
|
|
aria-controls="recovery-codes-section">
|
|
{{ __('View recovery codes') }}
|
|
</x-ts-button>
|
|
|
|
<x-ts-button x-show="showRecoveryCodes"
|
|
icon="eye-slash"
|
|
x-on:click="showRecoveryCodes = false"
|
|
aria-expanded="true"
|
|
aria-controls="recovery-codes-section">
|
|
{{ __('Hide recovery codes') }}
|
|
</x-ts-button>
|
|
|
|
@if (filled($recoveryCodes))
|
|
<x-ts-button x-show="showRecoveryCodes"
|
|
icon="arrow-path"
|
|
color="secondary"
|
|
outline
|
|
wire:click="regenerateRecoveryCodes"
|
|
loading="regenerateRecoveryCodes">
|
|
{{ __('Regenerate codes') }}
|
|
</x-ts-button>
|
|
@endif
|
|
</div>
|
|
|
|
<div x-show="showRecoveryCodes"
|
|
x-transition
|
|
id="recovery-codes-section"
|
|
class="relative overflow-hidden"
|
|
x-bind:aria-hidden="!showRecoveryCodes">
|
|
<div class="mt-3 space-y-3">
|
|
@error('recoveryCodes')
|
|
<x-ts-alert color="red" icon="x-circle" :text="$message" />
|
|
@enderror
|
|
|
|
@if (filled($recoveryCodes))
|
|
<div class="grid gap-1 rounded-lg bg-gray-100 p-4 font-mono text-sm dark:bg-dark-700"
|
|
role="list"
|
|
aria-label="{{ __('Recovery codes') }}">
|
|
@foreach ($recoveryCodes as $code)
|
|
<div role="listitem" class="select-text" wire:loading.class="opacity-50 animate-pulse">
|
|
{{ $code }}
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
<p class="text-xs text-gray-500 dark:text-dark-300">
|
|
{{ __('Each recovery code can be used once to access your account and will be removed after use. If you need more, click Regenerate codes above.') }}
|
|
</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|