toast_overlay 0.3.0 copy "toast_overlay: ^0.3.0" to clipboard
toast_overlay: ^0.3.0 copied to clipboard

An animated, themeable overlay toast for Flutter with an auto-dismiss countdown ring and an optional copyable support reference id.

toast_overlay #

An animated, themeable overlay toast for Flutter — with an auto-dismiss countdown ring, and an optional support reference id the user can copy.

Unlike a SnackBar, it renders into the root Overlay, so it shows above dialogs and bottom sheets and survives route changes. It has no dependency on your app's theme, assets or localisations — you inject those.

Three toasts stacked at the top:

Three stacked toasts

One anchored to the bottom:

A toast anchored to the bottom

And one carrying a support reference id, with its copy button:

An error toast with a reference id

Install #

flutter pub add toast_overlay

Or add it to pubspec.yaml yourself — it is a runtime dependency:

dependencies:
  toast_overlay: ^0.3.0

then:

flutter pub get

Use #

Initialise once with your root navigator key:

final navigatorKey = GlobalKey<NavigatorState>();

MaterialApp(navigatorKey: navigatorKey, /* … */);

Toast.init(navigatorKey: navigatorKey);

Then, from anywhere:

Toast.show(
  status: ToastStatus.success,
  title: 'Order placed',
  subtitle: 'Your position is now open.',
);
Parameter Default Meaning
status error, success, info, warning
title Falls back to the status default when empty
subtitle null Secondary line, up to 3 lines
referenceId null Shown with a copy button; disables auto-dismiss
position top top or bottom
offset kToolbarHeight Distance from the anchored edge
duration 3s null keeps it up until dismissed

Stacking #

By default each toast replaces the one on screen. Raise maxStack and they stack against their edge instead — the oldest drops off once the limit is hit:

Toast.init(
  navigatorKey: navigatorKey,
  maxStack: 3,      // 1 (the default) replaces instead of stacking
  stackSpacing: 8,  // gap between two cards
);

Top-anchored and bottom-anchored toasts stack separately, each against its own edge, and only the card nearest the edge keeps its offset.

Reference ids #

On an error you often want to hand the user something to quote to support. Pass a referenceId and the toast renders Ref: <id> with a copy button — and stops auto-dismissing, because a toast that vanishes while you are copying it is useless.

Toast.show(
  status: ToastStatus.error,
  title: 'Withdrawal failed',
  referenceId: response.traceId,
);

Theming #

Register a ToastTheme extension and the toast follows your light and dark themes:

MaterialApp(
  theme: ThemeData(extensions: const [ToastTheme(
    surface: Color(0xFFF7F8FA),
    borderColor: Color(0xFFE5E7EB),
    titleColor: Color(0xFF0A0C12),
    subtitleColor: Color(0xFF6B7280),
    closeIconColor: Color(0xFF9CA3AF),
    statusColors: {
      ToastStatus.success: ToastStatusColors(
        background: Color(0xFFD1FADF),
        foreground: Color(0xFF12B76A),
      ),
      // …
    },
  )]),
);

If you register nothing, it still works — the palette is derived from the ambient ColorScheme.

Corners #

cardRadius and iconRadius are BorderRadius, so corners can differ — 12 and 6 all round by default:

ToastTheme(
  // …
  cardRadius: BorderRadius.circular(20),
  iconRadius: const BorderRadius.only(
    topLeft: Radius.circular(16),
    bottomRight: Radius.circular(16),
  ),
);

Pass cardShape or iconShape instead when you want a shape of your own; they override the radii.

Type #

fontFamily swaps the typeface on every line. For finer control, titleStyle, subtitleStyle and referenceStyle are used exactly as given — a weight, colour or family you set there is never overwritten:

ToastTheme(
  // …
  fontFamily: 'Inter',
  titleStyle: TextStyle(fontSize: 15, fontWeight: FontWeight.w700),
  subtitleStyle: TextStyle(fontSize: 13, height: 1.3),
  referenceStyle: TextStyle(fontSize: 12, letterSpacing: 0.4),
);

Everything else #

ToastTheme also carries shadows, icons, and a glowBuilder for painting a decorative backdrop behind the card:

glowBuilder: (context, status) => Image.asset(
  'assets/${status.shortName}_glow.webp',
  fit: BoxFit.fitWidth,
  alignment: Alignment.centerRight,
),

The glows in the screenshots above ship with the example, not the package — see example/assets/ and example/lib/example_toast_theme.dart.

Localisation #

The package ships English defaults and takes the rest from you, so it never needs to own your ARB files:

Toast.init(
  navigatorKey: navigatorKey,
  strings: ToastStrings(
    error: l10n.toastTypeError,
    success: l10n.toastTypeSuccess,
    info: l10n.toastTypeInfo,
    warning: l10n.toastTypeWarning,
    referencePrefix: l10n.refPrefix,
    closeLabel: l10n.dismissNotification,
    copyReferenceLabel: l10n.copyReferenceId,
  ),
);

The two labels are the accessibility labels on the close and copy buttons; both buttons have 48×48 tap targets.

Without the global facade #

Toast is a convenience wrapper. Inject a ToastController instead if you prefer explicit dependencies — it is what the widget tests use:

final controller = ToastController(
  overlayResolver: () => navigatorKey.currentState?.overlay,
  strings: const ToastStrings(),
  logger: debugPrintToast,
);

controller.show(const ToastConfig(
  status: ToastStatus.info,
  title: 'Hello',
));

overlayResolver returning null makes show a safe no-op, which is what you want before the first route is mounted. The toast is still recorded in history, so nothing is silently lost.

History and logging #

The controller keeps the last 20 toasts for a debug screen, and can forward each one to your own logger:

Toast.init(navigatorKey: navigatorKey, logger: myLogger.info);

for (final entry in Toast.history.entries) {
  print(entry); // 14:03:21.881 [error] Withdrawal failed — Please contact support.
}

Behaviour notes #

  • Showing a toast replaces any toast already on screen, unless maxStack is above 1.
  • The countdown ring is only drawn while a toast is auto-dismissing.
  • The card is wrapped in a RepaintBoundary and passed as the child of its AnimatedBuilder, so the animation does not rebuild the content.
  • The toast respects SafeArea on the edge it is anchored to.

License #

MIT

1
likes
160
points
214
downloads
screenshot

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

An animated, themeable overlay toast for Flutter with an auto-dismiss countdown ring and an optional copyable support reference id.

Homepage
Repository (GitHub)
View/report issues

Topics

#toast #notification #snackbar #overlay

License

MIT (license)

Dependencies

figma_squircle, flutter, remixicon

More

Packages that depend on toast_overlay