fix: accessibility, theming, and focus-visibility improvements
Addresses critical and high-severity findings from UI audit: - C1: Define missing CSS tokens (--hover, --bg-primary/secondary/tertiary) fixing broken hover states and Slides Builder backgrounds - C2: Chart colors now read CSS custom properties at render-time via getChartTheme(), adapting tooltip, ticks, and grid to dark mode - C3: Multi-select ARIA fixed — label elements now carry role="option" and aria-selected for valid listbox semantics - H1/M1: Remove unused --gold and duplicate --primary tokens; replace all var(--primary) with var(--accent) throughout App.css - H3/H4: Focus-visible outlines added to all custom interactive elements (chips, controls, year buttons, hero button, multi-select trigger) - H5: access-badge--full hardcoded colors replaced with design tokens - H7: aria-pressed added to all chart toggle buttons - L1: Hardcoded #fff/white replaced with var(--text-inverse) - M4: index.html now preloads DM Serif Display, Outfit, and IBM Plex Sans Arabic — all fonts actually used in the app Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+35
-18
@@ -23,13 +23,11 @@
|
||||
--text-secondary: #334155;
|
||||
--text-muted: #64748b;
|
||||
--accent: #2563eb;
|
||||
--primary: #2563eb;
|
||||
--accent-light: #dbeafe;
|
||||
--success: #059669;
|
||||
--success-light: #d1fae5;
|
||||
--danger: #dc2626;
|
||||
--danger-light: #fee2e2;
|
||||
--gold: #b8860b;
|
||||
--brand-icon: #3b82f6;
|
||||
--brand-text: #1e3a5f;
|
||||
--text-inverse: #ffffff;
|
||||
@@ -44,6 +42,10 @@
|
||||
--shadow-sm: 0 1px 2px rgba(0,0,0,0.05);
|
||||
--shadow: 0 4px 12px rgba(0,0,0,0.08);
|
||||
--radius: 12px;
|
||||
--hover: var(--muted-light);
|
||||
--bg-primary: var(--surface);
|
||||
--bg-secondary: var(--bg);
|
||||
--bg-tertiary: var(--border);
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
@@ -56,7 +58,6 @@
|
||||
--text-secondary: #cbd5e1;
|
||||
--text-muted: #94a3b8;
|
||||
--accent: #3b82f6;
|
||||
--primary: #3b82f6;
|
||||
--accent-light: #1e3a5f;
|
||||
--success: #34d399;
|
||||
--success-light: #064e3b;
|
||||
@@ -88,7 +89,6 @@
|
||||
--text-secondary: #cbd5e1;
|
||||
--text-muted: #94a3b8;
|
||||
--accent: #3b82f6;
|
||||
--primary: #3b82f6;
|
||||
--accent-light: #1e3a5f;
|
||||
--success: #34d399;
|
||||
--success-light: #064e3b;
|
||||
@@ -226,7 +226,7 @@ html[dir="rtl"] {
|
||||
|
||||
.empty-state-action {
|
||||
padding: 10px 20px;
|
||||
background: var(--primary);
|
||||
background: var(--accent);
|
||||
color: var(--text-inverse);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
@@ -1089,7 +1089,7 @@ table tbody tr:hover {
|
||||
.drp-custom-field input[type="date"]:focus {
|
||||
outline: none;
|
||||
border-color: var(--accent);
|
||||
box-shadow: 0 0 0 2px rgba(37, 99, 235, 0.12);
|
||||
box-shadow: 0 0 0 2px var(--accent);
|
||||
}
|
||||
|
||||
.drp-custom-sep {
|
||||
@@ -1127,7 +1127,7 @@ table tbody tr:hover {
|
||||
.drp-apply {
|
||||
background: var(--accent);
|
||||
border: 1px solid transparent;
|
||||
color: #fff;
|
||||
color: var(--text-inverse);
|
||||
}
|
||||
|
||||
.drp-apply:hover {
|
||||
@@ -1301,7 +1301,7 @@ table tbody tr:hover {
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
color: var(--text-inverse);
|
||||
cursor: pointer;
|
||||
transition: opacity 150ms ease;
|
||||
}
|
||||
@@ -1398,8 +1398,8 @@ table tbody tr:hover {
|
||||
}
|
||||
|
||||
.access-badge--full {
|
||||
background: #d1fae5;
|
||||
color: #065f46;
|
||||
background: var(--success-light);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
@@ -1418,7 +1418,7 @@ table tbody tr:hover {
|
||||
|
||||
.btn-small.btn-primary {
|
||||
background: var(--accent);
|
||||
color: white;
|
||||
color: var(--text-inverse);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
@@ -1758,7 +1758,7 @@ tr.editing td {
|
||||
|
||||
.chart-metric-selector button.active {
|
||||
background: var(--surface);
|
||||
color: var(--primary);
|
||||
color: var(--accent);
|
||||
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
||||
font-weight: 600;
|
||||
}
|
||||
@@ -1792,7 +1792,7 @@ tr.editing td {
|
||||
}
|
||||
|
||||
.carousel:focus-visible {
|
||||
outline: 2px solid var(--primary);
|
||||
outline: 2px solid var(--accent);
|
||||
outline-offset: 4px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
@@ -1877,7 +1877,7 @@ tr.editing td {
|
||||
}
|
||||
|
||||
.carousel-dot.active {
|
||||
background: var(--primary);
|
||||
background: var(--accent);
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
@@ -1903,14 +1903,14 @@ tr.editing td {
|
||||
}
|
||||
|
||||
.carousel-dots.labeled .carousel-dot:hover {
|
||||
border-color: var(--primary);
|
||||
border-color: var(--accent);
|
||||
background: var(--bg);
|
||||
}
|
||||
|
||||
.carousel-dots.labeled .carousel-dot.active {
|
||||
width: auto;
|
||||
background: var(--primary);
|
||||
border-color: var(--primary);
|
||||
background: var(--accent);
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.carousel-dots.labeled .carousel-dot.active .dot-label {
|
||||
@@ -2082,7 +2082,7 @@ tr.editing td {
|
||||
|
||||
.mobile-nav-item:hover,
|
||||
.mobile-nav-item.active {
|
||||
color: var(--primary);
|
||||
color: var(--accent);
|
||||
background: rgba(37, 99, 235, 0.08);
|
||||
}
|
||||
|
||||
@@ -2833,6 +2833,23 @@ html[dir="rtl"] .exportable-chart-wrapper .chart-export-btn.visible {
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Focus Visible — Keyboard accessibility
|
||||
======================================== */
|
||||
|
||||
.drp-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.drp-year-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.drp-cancel:focus-visible,
|
||||
.drp-apply:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.nav-refresh-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.nav-lang-toggle:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.multi-select-trigger:focus-visible { outline: 2px solid var(--accent); outline-offset: -1px; }
|
||||
.toggle-switch button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.chart-metric-selector button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.nav-link:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.controls-reset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
.alt-filter-reset:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
|
||||
|
||||
/* ========================================
|
||||
Reduced Motion
|
||||
======================================== */
|
||||
|
||||
Reference in New Issue
Block a user