Skip to content

SnackBar with action no longer auto-dismiss #173084

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 13 commits into
base: master
Choose a base branch
from

Conversation

QuncCccccc
Copy link
Contributor

@QuncCccccc QuncCccccc commented Jul 31, 2025

Fixes #173000

This PR updated the default behavior for Snackbar with action:

  • SnackBars no longer auto-dismiss if SnackBar.action is not null.
  • To override the default behavior, this PR added a property persist for SnackBar.

Pre-launch Checklist

  • I read the [Contributor Guide] and followed the process outlined there for submitting PRs.
  • I read the [Tree Hygiene] wiki page, which explains my responsibilities.
  • I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement].
  • I signed the [CLA].
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is [test-exempt].
  • I followed the [breaking change policy] and added [Data Driven Fixes] where supported.
  • All existing and new tests are passing.

@github-actions github-actions bot added framework flutter/packages/flutter repository. See also f: labels. f: material design flutter/packages/flutter/material repository. labels Jul 31, 2025
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 correctly implements the dismissible property for SnackBar to control whether it dismisses after a timeout. The implementation is straightforward, and the new functionality is well-covered by a new test case. I've found one minor issue with a leftover debug print statement that should be removed.

@QuncCccccc QuncCccccc requested a review from chunhtai July 31, 2025 23:23
@QuncCccccc QuncCccccc marked this pull request as ready for review July 31, 2025 23:23
Copy link
Contributor

@victorsanni victorsanni left a comment

Choose a reason for hiding this comment

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

I'm wondering if the default behavior of a Snackbar with an action still timing out should be kept. Although changing the default will be a breaking change.

///
/// Defaults to true. If false, the snack bar is still there even after the
/// timeout, unless the user taps the action button or the close icon.
final bool dismissible;
Copy link
Contributor

Choose a reason for hiding this comment

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

Not sure if dismissible is the right term, since tapping the action button dismisses the snackbar even when dismissible is false. I think the timeout vs. non-timeout is what makes this API distinctive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks for helping review the change! Then maybe dismissAfterTimeout or autoDismiss? I'm bad at naming. Any better names are welcome!

I'm wondering if the default behavior of a Snackbar with an action still timing out should be kept.

The main concern is the breaking change. If we change the default, we might need to inform developers to change all existing use cases. Just checked the specs on M3 website, it mentioned auto-dismiss though. Maybe we can disable the auto-dismiss if action/close icon is not null? WDYT @victorsanni @chunhtai :) ?

Copy link
Contributor

Choose a reason for hiding this comment

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

Any better names are welcome!

Maybe something like canTimeout or shouldTimeout?

Maybe we can disable the auto-dismiss if action/close icon is not null?

The spec says "Snackbars with actions should remain on the screen until the user takes an action on the snackbar, or dismisses it." So we might have to change the default and inform developers. I opened #173127 to check how bad the breaking change will be.

But irrespective of that I think the new API is definitely useful.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused by the spec. I read through it and in some places it suggests that the snackbar always dismisses by itself, even with an action. Maybe there's someone material to clarify?

Copy link
Contributor

Choose a reason for hiding this comment

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

maybe persist?

If the spec is contradicting itself, you can file an issue using the template from here https://buganizer.corp.google.com/issues/394084228

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Filed a ticket: b/438264879

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I just renamed the property and will wait for responses from the material team:)

@QuncCccccc QuncCccccc force-pushed the make_snack_bar_dismissible branch from 883566c to f81edef Compare August 12, 2025 21:15
@@ -289,6 +289,7 @@ class SnackBar extends StatefulWidget {
this.showCloseIcon,
this.closeIconColor,
this.duration = _snackBarDisplayDuration,
this.persist = false,
Copy link
Contributor

Choose a reason for hiding this comment

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

What if developer wants it to not persist, but talkback is on? I think this may need to be nullable and if it is null, we can derive it from either action not null or accessibleNavigation is on. If it is set, we should respect it no matter what.

@QuncCccccc QuncCccccc force-pushed the make_snack_bar_dismissible branch from 9c7dbf7 to da486ab Compare August 14, 2025 23:48
@QuncCccccc QuncCccccc force-pushed the make_snack_bar_dismissible branch from 973b93b to 6991c52 Compare August 19, 2025 21:05
@@ -459,6 +460,14 @@ class SnackBar extends StatefulWidget {
/// * <https://material.io/design/components/snackbars.html>
final Duration duration;

/// Whether the snack bar will stay or auto-dismiss after timeout.
///
/// If true, the snack bar is still there even after the timeout, until the
Copy link
Contributor

Choose a reason for hiding this comment

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

maybe remains displayed or remains visible? To be more descriptive.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

/// If true, the snack bar is still there even after the timeout, until the
/// user taps the action button or the close icon. If false, the snack bar
/// will be dismissed after the timeout. If this is null but the snackbar
/// action is not null, the snackbar will persist as well.
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we are not relying on screen reader on/off. We can make this non-null and do something like

SnackBar(
  bool? persist
): this.persist = perisit ?? action != null;

Copy link
Contributor

Choose a reason for hiding this comment

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

this will mean snackbar with action never auto-dismisses. which is a breaking change. Is this intended?

Copy link
Contributor

Choose a reason for hiding this comment

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

yes, since this is the material guideline, we should make it the default and communicate to the developer.

Copy link
Contributor

Choose a reason for hiding this comment

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

I wasn't too sure before because I was waiting for material team's response, but now they do. so we should go with this breaking change

///
/// If true, the snack bar is still there even after the timeout, until the
/// user taps the action button or the close icon. If false, the snack bar
/// will be dismissed after the timeout. If this is null but the snackbar
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe

If not provided, this is set to true if [action] is not null

Copy link
Contributor

Choose a reason for hiding this comment

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

also consider separate each if sentence into a new paragraph for readability

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@github-actions github-actions bot added d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos labels Aug 19, 2025
@QuncCccccc QuncCccccc changed the title Make SnackBar dismissible after timeout SnackBar with action no longer auto-dismiss Aug 19, 2025
@QuncCccccc
Copy link
Contributor Author

Migration guide: flutter/website#12329

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, just one minor comment

@@ -198,23 +198,12 @@ class ScaffoldMessengerState extends State<ScaffoldMessenger> with TickerProvide
Queue<ScaffoldFeatureController<SnackBar, SnackBarClosedReason>>();
AnimationController? _snackBarController;
Timer? _snackBarTimer;
bool? _accessibleNavigation;
late bool? _accessibleNavigation;
Copy link
Contributor

Choose a reason for hiding this comment

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

why do we need late? or do you forgot to remove the nullable?

Copy link
Contributor Author

@QuncCccccc QuncCccccc Aug 21, 2025

Choose a reason for hiding this comment

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

When I removed the block of code in didChangeDependencies, I got this lint rule to add late to _accessibleNavigation. Seems we still need it to control whether SnackBars have animation when it's sliding in and out.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or change it to bool _accessibleNavigation = false;?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
d: api docs Issues with https://api.flutter.dev/ d: examples Sample code and demos f: material design flutter/packages/flutter/material repository. framework flutter/packages/flutter repository. See also f: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[VPAT][A11y] snackbar with action should not time out by default
3 participants