Globaler :focus-visible-Outline (var(--color-primary), 2px) — Tailwind 4 strippt die Browser-Defaults, ohne Fokus-Ring sind Tastatur-Nutzer blind. .sr-only-Utility (Standard-Rezept) und .skip-link in app.css. prefers- reduced-motion: schaltet alle Transitions/Animationen auf 0.01ms. Layout: Skip-Link "Zum Inhalt springen" → #main, main bekommt tabindex="-1" und id, html-lang wird via $effect reaktiv mit i18n.current synchronisiert (Initial-SSR rendert "de", Browser zieht nach). Header: nav-aria-label aus i18n (common.main_nav), Locale-Switcher-Label aus common.language_switcher. ToastStack: role=region + aria-live=polite, einzelne Toasts role=alert (error) bzw. status (success/warning), Schließen- Button-Label i18n-konform. Hover-only Delete-Buttons (Decks-Liste, Deck-Detail-Karten) bekommen focus-visible:opacity-100 — bisher waren sie für Tastatur-Nutzer unsichtbar. opacity-0 statt hidden, damit Tab-Order intakt bleibt. svelte-check 379 files 0 errors, prod-Build sauber. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
34 lines
1.1 KiB
Svelte
34 lines
1.1 KiB
Svelte
<script lang="ts">
|
||
import { toasts } from '$lib/stores/toasts.svelte.ts';
|
||
import { i18n, t } from '$lib/i18n/index.svelte.ts';
|
||
|
||
const closeLabel = $derived(i18n.current === 'en' ? 'Close' : 'Schließen');
|
||
</script>
|
||
|
||
{#if toasts.items.length > 0}
|
||
<div
|
||
class="fixed bottom-4 right-4 z-50 flex flex-col gap-2"
|
||
role="region"
|
||
aria-live="polite"
|
||
aria-label={t('common.notifications')}
|
||
>
|
||
{#each toasts.items as t (t.id)}
|
||
<div
|
||
class="flex items-start gap-3 rounded-lg px-4 py-3 shadow-lg max-w-sm border bg-[var(--color-card)] border-[var(--color-border)]"
|
||
class:text-[var(--color-success)]={t.kind === 'success'}
|
||
class:text-[var(--color-warning)]={t.kind === 'warning'}
|
||
class:text-[var(--color-danger)]={t.kind === 'error'}
|
||
role={t.kind === 'error' ? 'alert' : 'status'}
|
||
>
|
||
<span class="flex-1 text-sm">{t.message}</span>
|
||
<button
|
||
class="text-[var(--color-muted)] hover:text-[var(--color-fg)] text-lg leading-none"
|
||
onclick={() => toasts.dismiss(t.id)}
|
||
aria-label={closeLabel}
|
||
>
|
||
×
|
||
</button>
|
||
</div>
|
||
{/each}
|
||
</div>
|
||
{/if}
|