fix(frontend): accessibility fixes for TrainingHistory expand/collapse and FAILED badge

- Add aria-expanded + aria-controls to expand button (WCAG 4.1.2)
- Add id="training-history-rows" to tbody for aria-controls target
- Replace title= tooltip on FAILED badge with details/summary for keyboard
  and touch accessibility; add training_error_detail_label i18n key
- Use motion-safe:animate-pulse on RUNNING badge for prefers-reduced-motion

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-04-14 15:26:55 +02:00
parent 29b44e3f48
commit 83900de787
4 changed files with 15 additions and 3 deletions

View File

@@ -554,6 +554,7 @@
"training_history_col_cer": "Fehlerrate",
"training_status_done": "Fertig",
"training_status_failed": "Fehler",
"training_error_detail_label": "Fehlerdetails",
"training_status_running": "Läuft…",
"training_seg_heading": "Segmentierung trainieren",
"training_seg_description": "Starte ein neues Training mit annotierten Segmentierungsbereichen, um die Texterkennung zu verbessern.",

View File

@@ -554,6 +554,7 @@
"training_history_col_cer": "Error Rate",
"training_status_done": "Done",
"training_status_failed": "Failed",
"training_error_detail_label": "Error details",
"training_status_running": "Running…",
"training_seg_heading": "Train segmentation",
"training_seg_description": "Start a new training run using annotated segmentation regions to improve text detection.",

View File

@@ -554,6 +554,7 @@
"training_history_col_cer": "Tasa de error",
"training_status_done": "Listo",
"training_status_failed": "Error",
"training_error_detail_label": "Detalles del error",
"training_status_running": "Ejecutando…",
"training_seg_heading": "Entrenar segmentación",
"training_seg_description": "Inicia un nuevo entrenamiento con regiones de segmentación anotadas para mejorar la detección de texto.",

View File

@@ -52,7 +52,7 @@ function formatCer(cer: number | undefined | null): string {
<th class="hidden pb-2 text-right md:table-cell">{m.training_history_col_cer()}</th>
</tr>
</thead>
<tbody>
<tbody id="training-history-rows">
{#if runs.length === 0}
<tr>
<td colspan="5" class="py-4 text-center text-sm text-ink-2">
@@ -85,7 +85,6 @@ function formatCer(cer: number | undefined | null): string {
{:else if run.status === 'FAILED'}
<span
class="inline-flex items-center gap-1 rounded-sm bg-red-100 px-1.5 py-0.5 text-xs font-medium text-red-700"
title={run.errorMessage}
>
<svg
aria-hidden="true"
@@ -101,13 +100,21 @@ function formatCer(cer: number | undefined | null): string {
</svg>
{m.training_status_failed()}
</span>
{#if run.errorMessage}
<details class="mt-0.5">
<summary class="cursor-pointer text-xs text-red-700 underline">
{m.training_error_detail_label()}
</summary>
<p class="mt-1 text-xs text-red-600">{run.errorMessage}</p>
</details>
{/if}
{:else}
<span
class="inline-flex items-center gap-1 rounded-sm bg-yellow-100 px-1.5 py-0.5 text-xs font-medium text-yellow-700"
>
<span
aria-hidden="true"
class="h-1.5 w-1.5 animate-pulse rounded-full bg-yellow-500"
class="h-1.5 w-1.5 rounded-full bg-yellow-500 motion-safe:animate-pulse"
></span>
{m.training_status_running()}
</span>
@@ -128,6 +135,8 @@ function formatCer(cer: number | undefined | null): string {
<div class="mt-2 text-center">
<button
type="button"
aria-expanded={expanded}
aria-controls="training-history-rows"
class="text-xs font-medium text-ink-3 transition-colors hover:text-ink"
onclick={() => (expanded = !expanded)}
>