From 25066af67c8d099b04b4755c341bb1d6e4da96c5 Mon Sep 17 00:00:00 2001 From: fahed Date: Wed, 25 Mar 2026 18:23:04 +0300 Subject: [PATCH] Harden: Fix critical accessibility issues - Add aria-labels to icon-only buttons (refresh, language toggle) - Add aria-hidden to decorative SVGs - Add aria-label to data source select - Replace outline:none with visible focus rings on all inputs/selects - Add
landmark for screen reader navigation - Add prefers-reduced-motion: disable all animations for vestibular safety - Move error message inline style to CSS class - Add aria-label to both nav landmarks Co-Authored-By: Claude Opus 4.6 (1M context) --- src/App.css | 35 ++++++++++++++++++++++++++++++++--- src/App.tsx | 50 ++++++++++++++++++++++++++++---------------------- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/src/App.css b/src/App.css index 0cd4b4c..70523da 100644 --- a/src/App.css +++ b/src/App.css @@ -84,6 +84,17 @@ html[dir="rtl"] { background: var(--text-secondary); } +.error-container button:focus-visible { + outline: 2px solid var(--accent); + outline-offset: 2px; +} + +.error-message { + max-width: 400px; + text-align: center; + color: var(--text-muted); +} + /* Empty State */ .empty-state { display: flex; @@ -216,7 +227,8 @@ html[dir="rtl"] { } .data-source-select:focus { - outline: none; + outline: 2px solid var(--accent); + outline-offset: 1px; background-color: rgba(59, 130, 246, 0.12); } @@ -673,7 +685,8 @@ table tbody tr:hover { .control-group select:focus, .control-group input[type="date"]:focus { - outline: none; + outline: 2px solid var(--accent); + outline-offset: -1px; border-color: var(--accent); } @@ -1679,7 +1692,8 @@ table tbody tr:hover { .editor-section input:focus, .editor-section select:focus { - outline: none; + outline: 2px solid var(--accent); + outline-offset: -1px; border-color: var(--accent); } @@ -1988,6 +2002,21 @@ html[dir="rtl"] .chart-export-btn.visible { text-align: left !important; } +/* ======================================== + Reduced Motion + ======================================== */ + +@media (prefers-reduced-motion: reduce) { + *, *::before, *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } + .carousel-track { + transition: none; + } +} + /* ======================================== Loading Skeleton ======================================== */ diff --git a/src/App.tsx b/src/App.tsx index 86f8288..94017e6 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -95,7 +95,7 @@ function App() { return (

{t('app.error')}

-

+

{t(`errors.${error.type}`)}

@@ -106,10 +106,10 @@ function App() { return (
-