diff --git a/IMPROVEMENTS.md b/IMPROVEMENTS.md index d5e78ad..2ec8743 100644 --- a/IMPROVEMENTS.md +++ b/IMPROVEMENTS.md @@ -1,5 +1,18 @@ # PingDiff Improvement Log +## 2026-03-20 — Accessibility: ARIA labels, table semantics, and skip navigation + +Comprehensive a11y pass across the dashboard, navbar, and secondary pages. The site had no named navigation landmark, no skip links on 3 of 4 pages, tables without column scope attributes, charts completely invisible to assistive technology, and stat cards that conveyed quality purely through color (WCAG 1.4.1 violation). All fixed without new dependencies. + +Dashboard: skip link + main-content anchor, role="region" on stats grid, aria-label on each stat card with text description, aria-hidden on decorative icons, role="img" + aria-label on both charts, aria-label on table element, scope="col" on all th elements, time element for timestamps, aria-label on ping/loss cells so quality is communicated in text not just color. + +Navbar: aria-label="Main navigation" on nav element, aria-haspopup on mobile toggle, role="menu" on mobile menu container. + +Community and Download pages: both were missing skip-to-content links and main-content anchor targets entirely. + +**Files changed:** `web/src/app/dashboard/page.tsx`, `web/src/components/Navbar.tsx`, `web/src/app/community/page.tsx`, `web/src/app/download/page.tsx` +**Lines:** +64 / -30 + ## 2026-03-19 — Performance: Memoize dashboard derived state All derived values on the dashboard (filteredResults, avgPing, avgPacketLoss, avgJitter, regions, chartData, serverChartData) were being recomputed inline on every React render — including renders triggered by unrelated state changes like the loading flag toggling off. Wrapped each value in useMemo with the tightest possible dependency array, eliminating 5 O(n) reduce passes and 2 groupBy passes on every extraneous render. At current scale the savings are modest; at the 500-1000 result range the dashboard would hit without this change the difference is measurable. The memoized structure also makes data dependencies explicit and auditable at a glance. diff --git a/web/src/app/community/page.tsx b/web/src/app/community/page.tsx index 9899cd7..cd6b1ca 100644 --- a/web/src/app/community/page.tsx +++ b/web/src/app/community/page.tsx @@ -7,9 +7,12 @@ import { Footer } from "@/components/Footer"; export default function CommunityPage() { return (
+ + Skip to main content + -
+
{/* Coming Soon Banner */}
diff --git a/web/src/app/dashboard/page.tsx b/web/src/app/dashboard/page.tsx index 137c80e..aadfe87 100644 --- a/web/src/app/dashboard/page.tsx +++ b/web/src/app/dashboard/page.tsx @@ -226,10 +226,13 @@ export default function DashboardPage() { return (
+ + Skip to main content + {/* Main Content */} -
+

Dashboard

@@ -341,13 +344,20 @@ export default function DashboardPage() { ) : ( <> {/* Stats Cards */} -
-
+
+
- +
-
+
@@ -355,9 +365,12 @@ export default function DashboardPage() {
-
+
- +
@@ -374,23 +388,29 @@ export default function DashboardPage() {
-
+
- +
-
+
Variation
-
+
- +
-
+
Total tests
@@ -402,7 +422,7 @@ export default function DashboardPage() { {/* Ping History Chart */}

Ping History

-
+
@@ -430,7 +450,7 @@ export default function DashboardPage() { {/* Server Comparison Chart */}

Server Comparison

-
+
@@ -459,15 +479,18 @@ export default function DashboardPage() {
- +
- - - - - - + + + + + + @@ -482,9 +505,8 @@ export default function DashboardPage() { @@ -497,6 +519,7 @@ export default function DashboardPage() { ? "text-green-500" : "text-orange-500" }`} + aria-label={`${result.packet_loss} percent packet loss${result.packet_loss === 0 ? " — no loss" : ""}`} > {result.packet_loss}% @@ -504,7 +527,9 @@ export default function DashboardPage() { {result.isp || "Unknown"} ))} diff --git a/web/src/app/download/page.tsx b/web/src/app/download/page.tsx index c72f3d1..8c3d4b7 100644 --- a/web/src/app/download/page.tsx +++ b/web/src/app/download/page.tsx @@ -65,10 +65,13 @@ export default function DownloadPage() { return (
+ + Skip to main content + {/* Main Content */} -
+

Download PingDiff

diff --git a/web/src/components/Navbar.tsx b/web/src/components/Navbar.tsx index 880baec..bbbe061 100644 --- a/web/src/components/Navbar.tsx +++ b/web/src/components/Navbar.tsx @@ -24,7 +24,7 @@ export function Navbar() { const isDownload = (href: string) => href === "/download"; return ( -

ServerPingJitterLossISPTimeServerPingJitterLossISPTime
{result.ping_avg}ms - {new Date(result.created_at).toLocaleDateString()} +