Skip to content

feat(a11y): announce new DX spot arrivals via aria-live (#997)#1083

Merged
accius merged 1 commit into
accius:Stagingfrom
chrisdebian:feat/dx-spot-aria-live
Jun 12, 2026
Merged

feat(a11y): announce new DX spot arrivals via aria-live (#997)#1083
accius merged 1 commit into
accius:Stagingfrom
chrisdebian:feat/dx-spot-aria-live

Conversation

@chrisdebian

Copy link
Copy Markdown

Summary

  • Adds useDXSpotAnnouncements hook that watches the already-filtered spot list from useDXClusterData and emits a polite aria-live announcement when new spots arrive
  • Single new spot: "New DX spot: G0ABC on 14.070 MHz"; multiple: "3 new DX spots, latest: G0ABC on 14.070 MHz"
  • Throttled to at most one announcement per 10 seconds to avoid flooding on active bands; text clears after 5 seconds
  • Follows the same pattern as useLightningAnnouncements and useSatelliteAnnouncements
  • 9 unit tests covering: baseline (no announcement on mount), single/multi-spot announce, kHz→MHz conversion, cleardown, throttle/cooldown, and empty list

Why polite

A new DX spot is interesting but not safety-critical. assertive would interrupt what the screen-reader is currently reading; polite waits for a natural pause, which is the right call here.

Why the filtered list

The hook receives dxClusterData.spots — the list already filtered by the user's active DX filters. A user who has narrowed to, say, EU stations on 20 m FT8 wants announcements only for those spots, not every spot that arrives on the cluster.

Test plan

  • Add DX Cluster panel; set a band/mode filter; wait for new spots — screen reader should announce them without interrupting
  • Verify no announcement fires on initial load (baseline behaviour)
  • Confirm rapid spot batches are throttled (at most one announcement per 10 s)
  • Run npm test — 488 passed, 0 regressions

Closes part of #997.

Adds `useDXSpotAnnouncements` hook that watches the already-filtered DX
spot list and emits a polite aria-live announcement when new spots arrive.
Throttled to at most one announcement per 10 seconds to prevent flooding
on active bands; text clears after 5 seconds.  Single new spot: "New DX
spot: G0ABC on 14.070 MHz"; multiple: "3 new DX spots, latest: …".

Follows the same pattern as useLightningAnnouncements and
useSatelliteAnnouncements. 9 unit tests covering baseline, announce,
multi-spot, kHz conversion, cleardown, and throttle/cooldown behaviour.

@accius accius left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean work, and the pattern reuse from the lightning/satellite announcers makes this an easy read. I verified the premise in useDXClusterData: applyFilters runs before setSpots, so the hook really does receive only spots matching the user's active filters, and polite is the right level for informational traffic (lightning stays assertive for the safety case). The null-baseline trick so the first non-empty fetch doesn't announce 500 spots at once is exactly the failure mode I would have probed for, and there's a test pinning it.

Two observations, neither blocking:

  • Spots that arrive during the 10s cooldown are added to the seen set without ever being announced, so they're skipped permanently rather than queued. I think that's the right call for a polite region (a backlog of stale announcements is worse than a missed one), just confirming it's intentional since the test suite pins it.
  • newSpots[0] as "latest" leans on the server list being newest-first, which it is today.

CI green including your 8 new tests on both Node versions.

K0CJH

@accius accius merged commit b4d9a9d into accius:Staging Jun 12, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants