The board becomes readable
The game board stops being hidden from assistive technology and becomes a read-only grid that can be explored without taking control away from word input.
The board was the centre of the game for sighted players and deliberately absent for screen readers. That had been a reasonable boundary while the primary interaction stayed in the word input and the game log carried the history, but it also meant that a player could not inspect where either snake or any fruit currently sat. The goal was to expose the board as a second, read-only surface without turning arrow keys into another way to steer the snake.
An explorer, not a controller#
The design work settled three choices before implementation started: whether the board should behave as a document, whether it needed application-style keyboard control, or whether the standard ARIA grid pattern already covered the job. A grid won. Tab and skip links move into or out of it, arrow keys move between cells, and movement clamps at the edges rather than wrapping. The focused row and column live in their own Svelte state, so a turn can replace the board underneath them without throwing the reader back to the first cell.
<div role="grid" aria-label={ui.boardGridLabel(width, height)}>
<div role="row">
<div
role="gridcell"
tabindex={nav.tabIndexFor(y, x)}
aria-label={describeBoardCell(cell, isTail, y, x, options)}
/>
</div>
</div>
The distinction between exploring and playing is load-bearing. Word input remains the way to control the snake, while the grid describes the current result at the player’s own pace. Daily cells can say “snake head” or “snake tail”; AI Duel and PvP need “your” and “their” versions, with the existing viewer transform deciding ownership before the board renders. Fruit descriptions reuse the same localized content that already explains their type, value, and origin, avoiding a second accessibility-only account of the game rules.
The board needed to become readable without becoming another controller.
Announce change without stealing focus#
One gap remained after choosing roving focus: screen readers announce a cell when focus moves to it, but not when the snake or a fruit changes the cell while focus stays put. A small scoped live region now reports only that delta, such as “now: apple”. It stays silent during navigation because the gridcell label already carries the full row, column, and content. That separation avoids reading the same information twice and lets focus survive every animation step.
The implementation covers Daily, AI Duel, and PvP with one navigation module and mode-specific descriptions. Automated checks exercise the grid roles, skip-link focus, clamped arrow movement, and an axe scan of the board, with 1,660 existing and new tests passing alongside them. The remaining check is deliberately manual: VoiceOver, NVDA, and TalkBack still need a verification pass on real screen-reader behavior. The markup is now ready for that test, and any differences between those readers can be handled without reopening the interaction model.