mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix VoiceOver tab activation by adding tappable behavior to SemanticTab (#170076)
## Description This pull request fixes VoiceOver tab activation by adding tappable behavior to the SemanticTab class in the Flutter web engine. The fix ensures that tabs can be properly activated using assistive technology commands like VoiceOver's ctrl-option-space, making tab navigation fully accessible for screen reader users. ## Before When using VoiceOver to navigate tabs in a Flutter web app, users were unable to activate tabs using the standard VoiceOver activation command (ctrl-option-space). The SemanticTab class was missing the Tappable semantic behavior that enables assistive technology interaction, causing screen readers to treat tabs as non-interactive elements despite having tap handlers in the Flutter framework. **Before behavior:** https://tab-0605-before.web.app/ - Navigate to a tab using VoiceOver (ctrl-option-arrow) - Attempt to activate the tab with ctrl-option-space - Tab does not respond to activation command - Users cannot switch between tabs using assistive technology ## After VoiceOver and other screen reader users can now properly activate tabs using standard assistive technology commands. Tabs respond correctly to ctrl-option-space and other activation gestures, providing full keyboard accessibility for tab navigation. **After behavior:** https://tab-0605-after.web.app/ - Navigate to a tab using VoiceOver (ctrl-option-arrow) - Activate the tab with ctrl-option-space - Tab switches correctly, displaying the associated tab panel - Consistent behavior across all assistive technologies ## Changes Made - Added `addTappable()` call to `SemanticTab` constructor in `tabs.dart` - Added test case "tab with tap action" to verify DOM elements receive the `flt-tappable` attribute - Ensures tabs with `hasTap: true` are properly marked as interactive for assistive technologies ## Testing Added unit test that verifies: - Tabs with tap actions receive the `flt-tappable` DOM attribute - SemanticTab properly integrates with the existing tappable behavior system ## Issue Fixed This PR addresses GitHub Issue #169279, which reports that VoiceOver doesn't allow users to click tabs in Flutter web applications. ## Pre-launch Checklist - [x] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [x] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [x] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [x] I signed the [CLA]. - [x] I listed at least one issue that this PR fixes in the description above. - [x] I updated/added relevant documentation (doc comments with `///`). - [x] I added new tests to check the change I am making, or this PR is [test-exempt]. - [x] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [x] All existing and new tests are passing.
This commit is contained in:
parent
8caedde6cc
commit
ea83a6a072
@ -19,6 +19,7 @@ class SemanticTab extends SemanticRole {
|
||||
preferredLabelRepresentation: LabelRepresentation.ariaLabel,
|
||||
) {
|
||||
setAriaRole('tab');
|
||||
addTappable();
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@ -4297,6 +4297,26 @@ void _testTabs() {
|
||||
expect(object.element.getAttribute('role'), 'tab');
|
||||
});
|
||||
|
||||
test('tab with tap action', () {
|
||||
semantics()
|
||||
..debugOverrideTimestampFunction(() => _testTime)
|
||||
..semanticsEnabled = true;
|
||||
|
||||
final SemanticsTester tester = SemanticsTester(owner());
|
||||
tester.updateNode(
|
||||
id: 0,
|
||||
role: ui.SemanticsRole.tab,
|
||||
hasTap: true,
|
||||
rect: const ui.Rect.fromLTRB(0, 0, 100, 50),
|
||||
);
|
||||
tester.apply();
|
||||
|
||||
final SemanticsObject object = tester.getSemanticsObject(0);
|
||||
expect(object.semanticRole?.kind, EngineSemanticsRole.tab);
|
||||
expect(object.element.getAttribute('role'), 'tab');
|
||||
expect(object.element.hasAttribute('flt-tappable'), isTrue);
|
||||
});
|
||||
|
||||
test('nodes with tab panel role', () {
|
||||
semantics()
|
||||
..debugOverrideTimestampFunction(() => _testTime)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user