Skip to content

Snackbar a11y fix #173686

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open

Conversation

nancyflutter
Copy link

@nancyflutter nancyflutter commented Aug 13, 2025

Replace this paragraph with a description of what this PR is changing or adding, and why. Consider including before/after screenshots.

List which issues are fixed by this PR. You must list at least one issue. An issue is not required if the PR fixes something trivial like a typo.

If you had to change anything in the flutter/tests repo, include a link to the migration guide as per the breaking change policy.

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

Copy link

google-cla bot commented Aug 13, 2025

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces an accessibility improvement for SnackBars by explicitly announcing their content using SemanticsService.announce. This is achieved by wrapping the showSnackBar logic in a new showAccessibleSnackBar helper method. The changes also include updates to the corresponding tests.

My review identifies a few areas for improvement:

  • The use of Future.delayed for the semantics announcement could be fragile. I've suggested a more robust alternative.
  • The test file contains duplicate imports that should be cleaned up.
  • A useful assertion was removed from a test, and I recommend re-adding it to improve test robustness.

Overall, this is a good step towards better accessibility. Addressing the feedback will make the implementation more solid.

Comment on lines 43 to 46
Future<void>.delayed(const Duration(milliseconds: 100), () {
debugPrint('Announcing: $message');
SemanticsService.announce(message, TextDirection.ltr);
});
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The use of Future.delayed with a fixed duration can be fragile. The announcement might occur before the SnackBar is fully visible, especially on slower devices or if animations are disabled. For more robustness, consider using WidgetsBinding.instance.addPostFrameCallback to schedule the announcement after the current frame has been rendered. This ensures the SnackBar is on screen when the announcement is made.

    WidgetsBinding.instance.addPostFrameCallback((_) {
      debugPrint('Announcing: $message');
      SemanticsService.announce(message, TextDirection.ltr);
    });

Comment on lines 10 to 13
import 'package:a11y_assessments/use_cases/snack_bar.dart';
import 'package:flutter_test/flutter_test.dart';

import 'test_utils.dart';
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This file contains duplicate import statements. Please remove the redundant imports on lines 10-13 to improve code clarity and maintainability.

import 'package:flutter_test/flutter_test.dart';

import 'test_utils.dart';

void main() {
testWidgets('snack bar can run', (WidgetTester tester) async {
await pumpsUseCase(tester, SnackBarUseCase());
const String snackBarText = 'Awesome Snackbar!';
expect(find.text(snackBarText), findsNothing);
await tester.tap(find.text('Show Snackbar'));
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The assertion expect(find.text(snackBarText), findsNothing); was removed from this test. This check is valuable because it verifies that the SnackBar is not visible immediately after the tap event and before tester.pump() is called. Restoring this assertion would make the test more thorough by explicitly checking the state transition.

    await tester.tap(find.text('Show Snackbar'));
    expect(find.text(snackBarText), findsNothing);

);

Future<void>.delayed(const Duration(milliseconds: 100), () {
debugPrint('Announcing: $message');
Copy link
Contributor

Choose a reason for hiding this comment

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

let's remove print statement

),
);

Future<void>.delayed(const Duration(milliseconds: 100), () {
Copy link
Contributor

Choose a reason for hiding this comment

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

we should only do this for MediaQueryData.supportsAnnounce is true, you can get this from MediaQuery.of(context).

await tester.pumpAndSettle();
final Finder findHeadingLevelOnes = find.bySemanticsLabel('SnackBar Demo');
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you add a expect that the message is announced? See this file for example
https://github.com/flutter/flutter/blob/master/packages/flutter/test/semantics/semantics_service_test.dart

…et tests to verify Snackbar visibility and announcement.
@@ -5,8 +5,6 @@ version: 5.0.0+5
environment:
sdk: ^3.8.0-0

resolution: workspace
Copy link
Contributor

Choose a reason for hiding this comment

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

why this change?

Copy link
Author

Choose a reason for hiding this comment

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

This line was removed because it was not required for this package to work correctly, and it was causing resolution issues during local development. Let me know if you'd prefer to keep it.

@@ -1,8 +1,8 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Copy link
Contributor

Choose a reason for hiding this comment

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

can we revert this?

Copy link
Author

Choose a reason for hiding this comment

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

sure

@@ -1,27 +1,78 @@
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
Copy link
Contributor

Choose a reason for hiding this comment

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

same

Copy link
Author

Choose a reason for hiding this comment

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

okay


// Verify the message was announced for accessibility
await tester.pumpAndSettle();
// Note: In test environment, SemanticsService.announce may not work the same way
Copy link
Contributor

Choose a reason for hiding this comment

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

In test environment the entire widgets binding are mocked, and we should have api to catch any calls to SystemChannel.accessibility, which is where the announcement is sent to

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for pointing that out! I've updated the test to intercept SystemChannels.accessibility and verify that the correct announcement message is sent. Let me know if you have any suggestions on improving the implementation.

Copy link
Contributor

Choose a reason for hiding this comment

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

This seems not addressed. Do you forget to push the change?

Copy link
Author

Choose a reason for hiding this comment

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

Hi @chunhtai, thanks for the review! I just pushed the update that intercepts SystemChannels.accessibility and verifies the announcement message in the latest commit. Could you please check if the change is now visible on your end? Let me know if anything else needs to be addressed. Thanks!

@chunhtai chunhtai self-requested a review August 18, 2025 18:05
@@ -29,6 +29,25 @@ class MainWidget extends StatefulWidget {
class MainWidgetState extends State<MainWidget> {
String pageTitle = getUseCaseName(SnackBarUseCase());

/// Shows a SnackBar with accessibility announcement support.
/// This method checks if the device supports announcements and announces
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
/// This method checks if the device supports announcements and announces
///
/// This method checks if the device supports announcements and announces

Copy link
Contributor

Choose a reason for hiding this comment

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

a new line after the first paragraph


// Verify the message was announced for accessibility
await tester.pumpAndSettle();
// Note: In test environment, SemanticsService.announce may not work the same way
Copy link
Contributor

Choose a reason for hiding this comment

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

This seems not addressed. Do you forget to push the change?

@nancyflutter nancyflutter requested a review from chunhtai August 20, 2025 12:59
Copy link
Contributor

@chunhtai chunhtai left a comment

Choose a reason for hiding this comment

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

LGTM

@loic-sharma
Copy link
Member

@nancyflutter Could you sign the CLA?

@chunhtai
Copy link
Contributor

also, looks like you forgot to sign the cla

Co-authored-by: Loïc Sharma <737941+loic-sharma@users.noreply.github.com>
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.

3 participants