Skip to content

A button that announces itself carries the tap it is announcing - #620

Open
maximsan wants to merge 1 commit into
mainfrom
fix/announced-buttons-cannot-be-pressed
Open

maximsan wants to merge 1 commit into
mainfrom
fix/announced-buttons-cannot-be-pressed

Conversation

@maximsan

Copy link
Copy Markdown
Owner

Why

Closes #487. Nodes flagged isButton carried no tap action, so VoiceOver and
TalkBack announced buttons that did nothing when activated.

Watch for

  • Twenty-seven sites, not the nine the ticket lists, and three of its nine
    named the wrong file: the drill rows are ReplayRow, the tile is
    match_tile.dart, and path_module_section.dart has no button at all — its
    excluded node is a label rewrite. The new guard test found the true set.
  • Disclosure and ProfileCard take the tap conditionally. Their
    excludeSemantics is itself conditional, and passing onTap beside a live
    InkWell turns the annotation into a node boundary: the row splits in two
    and the button flag lands on the node that does not carry the label. An
    existing assertion in help_support_screen_test.dart caught that.
  • One behaviour change beyond the mechanical fix. The Dictionary path row
    announced button: true while its lesson id was still unresolved, so it had
    nothing to press even after the tap was passed. It is now a button only once
    there is an id.
  • Doc comments were trimmed in nine touched files. The six-line cap is a
    write-time hook, so a touched file would not save until it was clean. Design
    rationale was cut rather than moved; reward_row, challenge_offer_row and
    sound_toggle lost the most, and it may belong in docs/. I also dropped a
    citation of ADR-0005 for "peak intent" — that ADR is about mini-games and
    the phrase is in docs/design/PRODUCT.md.

Checks

The widget test performs the announced action and asserts the handler runs,
rather than only checking the flag. The guard reads source text, so it pairs
the flag with the action but cannot see that a handler is nullable — that
pairing is still by hand. No real VoiceOver or TalkBack pass was made, and
nothing on screen changes.

`Semantics(button: true, excludeSemantics: true)` reads a tappable row as
one announcement, but the exclusion drops the child's tap action along with
its text. What is left says "button" and carries nothing to press.

Twenty-seven nodes were in that state, not the nine the ticket names: the
shared frame and replay row cover the drill rows it lists, and match_tile
rather than match_board_view holds the tile. The handler now goes on the
Semantics as well as the child.

Where the exclusion is conditional — Disclosure, ProfileCard — the tap is
carried only when the child's own is being dropped. Passing it beside a live
InkWell splits the row into two nodes and takes the button flag off the one
that carries the label.

A guard test reads every source under lib/ and fails if the flag and the
action come apart again, and BorderedTapRow has a widget test that performs
the announced action and checks the handler runs.

Closes #487
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.

Buttons that announce themselves but cannot be pressed

1 participant