island_snack 0.1.0 copy "island_snack: ^0.1.0" to clipboard
island_snack: ^0.1.0 copied to clipboard

PlatformiOS

Dynamic Island-style notifications for Flutter iOS apps. Spring physics animations that expand from the island position.

island_snack #

pub package License: MIT

Dynamic Island-style notifications for Flutter iOS apps. Expands from the island position with spring physics animations, staggered content reveal, and swipe-to-dismiss.

On devices with a Dynamic Island the pill starts at the exact hardware cutout position. On older devices it falls back to a centered top-of-screen pill.

Features #

  • Spring physics expand/collapse (underdamped overshoot + critically-damped retract)
  • Staggered per-element content reveal (icon, title, subtitle, action)
  • Preset styles: success, error, warning, info, loading
  • Queue system with normal and urgent priority
  • ID-based in-place updates (e.g. loading -> success)
  • Swipe-to-dismiss
  • Action buttons, progress bars, custom leading widgets
  • IslandSnackTheme for global color/font/duration/haptic overrides
  • onDismissed / onShown callbacks
  • Accessibility: VoiceOver live region, semantic labels

Platform support #

Platform Supported
iOS Yes
Android No
Web No

Installation #

dependencies:
  island_snack: ^0.1.0

Quick start #

Wrap your app with IslandSnackTheme (optional) and call the static methods:

import 'package:island_snack/island_snack.dart';

// Optional: wrap your app for global theming
IslandSnackTheme(
  successColor: Color(0xFF7E9B72),
  fontFamily: 'SF Pro',
  child: MaterialApp(...),
);

// Show notifications from anywhere
IslandSnack.success(context, title: 'Saved');
IslandSnack.error(context, title: 'Upload failed', subtitle: 'Try again');
IslandSnack.warning(context, title: 'Offline');
IslandSnack.info(context, title: '12 items archived');
IslandSnack.loading(context, id: 'sync', title: 'Syncing...');

// Dismiss
IslandSnack.dismiss();
IslandSnack.dismissAll();

API reference #

Preset methods #

Method Icon Default color Default haptic
IslandSnack.success() checkmark #7E9B72 sage light
IslandSnack.error() x-circle #B87068 rose medium
IslandSnack.warning() warning #C9834E terracotta light
IslandSnack.info() info #C8B9A0 sand light
IslandSnack.loading() spinner #8E8E93 gray none

All preset methods accept:

IslandSnack.success(
  context,
  title: 'Saved',             // required
  subtitle: 'To favorites',   // optional
  id: 'save',                 // optional — for in-place updates
  duration: IslandSnackDuration.long,
  customDuration: Duration(seconds: 4),  // overrides enum duration
  haptic: IslandSnackHaptic.light,
  priority: IslandSnackPriority.normal,
  action: IslandSnackAction(label: 'Undo', onPressed: () {}),
  leading: Icon(Icons.star),  // custom leading widget
  onTap: () {},
  onDismissed: () {},
  onShown: () {},
);

IslandSnack.show() #

Full control — same parameters as above plus:

IslandSnack.show(
  context,
  title: 'Processing',
  style: IslandSnackStyle(
    accentColor: Colors.purple,
    iconData: Icons.auto_awesome,
  ),
  progress: 0.65,      // 0.0 to 1.0
  isLoading: true,      // shows spinner instead of icon
);

Dismiss #

IslandSnack.dismiss();     // dismiss current
IslandSnack.dismissAll();  // dismiss current + clear queue

State getters #

IslandSnack.isShowing;       // bool — whether a notification is visible
IslandSnack.isDynamicIsland;  // bool? — null if not yet detected

ID-based updates #

Assign the same id to replace a notification in-place:

IslandSnack.loading(context, id: 'upload', title: 'Uploading...');

// Later:
IslandSnack.success(context, id: 'upload', title: 'Upload complete!');

Queue behavior #

  • Normal priority: queued — shows after the current notification dismisses.
  • Urgent priority: clears queue and replaces current immediately.
  • ID-based: if a notification with the same ID is showing, it is dismissed and replaced.

Customization #

Theme #

IslandSnackTheme(
  successColor: Color(0xFF7E9B72),
  errorColor: Color(0xFFB87068),
  warningColor: Color(0xFFC9834E),
  infoColor: Color(0xFFC8B9A0),
  loadingColor: Color(0xFF8E8E93),
  fontFamily: 'SF Pro',
  shortDuration: Duration(seconds: 2),
  longDuration: Duration(seconds: 3),
  actionDuration: Duration(seconds: 5),
  defaultHaptic: IslandSnackHaptic.light,
  child: MaterialApp(...),
);

Custom style #

IslandSnack.show(
  context,
  title: 'Custom',
  style: IslandSnackStyle(
    accentColor: Colors.purple,
    iconData: Icons.auto_awesome,
  ),
);

Callbacks #

IslandSnack.success(
  context,
  title: 'Done',
  onShown: () => print('Visible'),
  onDismissed: () => print('Gone'),
);

Accessibility #

  • The notification pill is wrapped in a Semantics widget with liveRegion: true, so VoiceOver announces it automatically.
  • Action buttons have Semantics(button: true).
  • Decorative elements (accent line, debug overlay) are excluded from the semantic tree.

License #

MIT — see LICENSE.

1
likes
150
points
9
downloads

Documentation

API reference

Publisher

verified publisheralejandrogarcia.io

Weekly Downloads

Dynamic Island-style notifications for Flutter iOS apps. Spring physics animations that expand from the island position.

Repository (GitHub)

Topics

#notification #snackbar #dynamic-island #ios #animation

License

MIT (license)

Dependencies

device_info_plus, figma_squircle, flutter

More

Packages that depend on island_snack