Skip to content

feat: Screenreader announcements for move mode#9731

Open
mikeharv wants to merge 3 commits intoRaspberryPiFoundation:v13from
mikeharv:move-announcements
Open

feat: Screenreader announcements for move mode#9731
mikeharv wants to merge 3 commits intoRaspberryPiFoundation:v13from
mikeharv:move-announcements

Conversation

@mikeharv
Copy link
Copy Markdown
Contributor

The basics

The details

Resolves

Fixes #9686

Proposed Changes

This PR introduces ARIA live region announcements for moving blocks (both keyboard-driven move mode and standard mouse/pointer drags).

Key changes include:

  • Added computeMoveLabel to generate more descriptive and context-aware move announcements.
  • Introduced dynamic preposition selection (before, after, inside, around) based on connection types.
  • Added disambiguation logic for cases where multiple compatible connections exist, including:
    • Input label subsets (e.g. distinguishing between if, else if, else statement inputs)
    • Existing field-based labels (e.g. operator text like =)
    • Index-based fallbacks for unlabeled inputs (e.g. value inputs on text_join blocks)
  • Added BlockSvg.getStackBlocksCountLabel to announce stack size when moving multiple connected "stack blocks".
  • Integrated the new announcement logic into BlockDragStrategy.
  • Updated Field.getAriaValue to use getText instead of getValue, improving readout of some custom fields.
  • Updated getParentInputLabel to ignore parent blocks if they are the insertion marker for the moving block
  • Refactored getInputLabels to use a new Input.getLabel method which now also correctly ignore insertion markers.

If a block is moving without a candidate connection we will simply announce moving [block label] on workspace. It was decided that omitting cardinal directions is beneficial here as the user likely knows which arrow keys they have pressed (or which way they are dragging).
If a user cancels a movement, this is also announced. There is not currently an announcement when a movement is completed (ie. endDrag()).
Other announcement labels follow this format:
Moving [block label] [disambiguation info] *preposition* [target block label] [disambiguation info]
Disambiguation info is of course optional, as is the block label for the moving block if the user has already been moving (in drag() as opposed to startDrag()). Only the preposition and the target connection's block label are always included. "Before" and "after" are exclusively reserved for stacked blocks while "inside" and "around" are use for input/output connections and statement inputs.

Examples:

startDrag() drag()
image image
moving [print “ def ”] after [print “ abc ”]
(Candidate found on start of move)
moving [] before [print “ abc ”]
(Block label omitted for successive moves)
image image
moving [if, do] inside [repeat 10, times, do] [] moving [] [] around [repeat 10, times, do]
image
moving [2 stack blocks] inside [if false, do, else if true, do, else if false or false, do, else] [else if false or false, do]

Note: Sometimes the block labels feel exceedingly verbose, especially when we need to iterate a portion to disambiguate the connection. As a follow-up, I think it could be worth being able to compute a terser label for a block with multiple connections.

Reason for Changes

This provides an improved version of screen reader announcements for move mode that was based on micro:bit's testing. Key improvements include:

  • correct prepositional descriptions
  • terser announcements (often omitting superfluous block labels)
  • disambiguation labels for multiple compatible connections with a target block.

Test Coverage

Added and extended tests in the keyboard movement test suite to verify ARIA announcements.

Coverage includes:

  • Announcements when starting a move (single block and multi-block stacks)
  • Correct prepositions for different connection types (before, after, inside, around)
  • Announcements when no connection candidate is available (workspace movement)
  • Disambiguation behavior when multiple compatible connections exist:
    • Statement inputs (e.g. if, else if, else)
    • Value inputs using (e.g. in logic_compare blocks)
    • Fallback to input index for unlabeled inputs (e.g. in text_join)
  • Ensures announcements include expected labels and prepositions and exclude unnecessarily verbose labels.

Tests use real keyboard movement flows and assert against the ARIA live region output.

Documentation

TSDocs were added/updated as needed.

Additional Information

Tests were designed to be resilient to minor wording or localization changes by asserting substrings rather than full string equality. This should make the tests less brittle as we potentially iterate on block and field labels.

@mikeharv mikeharv requested a review from a team as a code owner April 17, 2026 19:24
@mikeharv mikeharv requested a review from gonfunko April 17, 2026 19:24
@github-actions github-actions bot added the PR: feature Adds a feature label Apr 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

PR: feature Adds a feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants