Skip to content

6639835/Toast

Repository files navigation

Toast

A production-ready iOS toast notification library that feels unmistakably Apple-native.

Toast provides transient, non-blocking feedback notifications for iOS 17+ apps — restrained visuals, spring-based motion, full accessibility support, and a minimal public surface. Zero dependencies.


Requirements

  • iOS 17+
  • Swift 5.9+
  • Xcode 15+

Installation

Swift Package Manager

Add Toast to your Package.swift:

dependencies: [
    .package(url: "https://github.com/6639835/Toast.git", from: "1.0.0")
]

Or add it via Xcode: File → Add Package Dependencies and enter the repository URL.


Quick Start

1. Install the host modifier once at your scene root:

@main
struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .toastHost()
        }
    }
}

2. Show toasts from anywhere:

// From a view model or async action:
ToastManager.shared.show(.success, title: "Photo saved")
ToastManager.shared.show(.error, title: "Upload failed", subtitle: "Check your connection")

// From a SwiftUI view via environment:
@Environment(\.toastManager) var toastManager

Button("Save") {
    toastManager?.show(.success, title: "Saved")
}

3. Binding-driven presentation:

@State private var toast: ToastItem?

Button("Save") {
    toast = ToastItem(kind: .success, title: "Saved")
}
.toast(item: $toast)

API Reference

ToastManager

The primary entry point. One instance per UIWindowScene.

Method Description
ToastManager.shared Convenience accessor for single-scene apps
ToastManager.manager(for:) Per-scene accessor for multi-scene apps
show(_ kind:title:subtitle:duration:position:) Show a toast with semantic convenience
show(_ item:) Show a fully configured ToastItem
dismissCurrent() Dismiss the visible toast immediately
dismiss(id:) Dismiss a toast by its UUID
cancelAll() Cancel all pending and visible toasts
removeManager(for:) Clean up when a scene disconnects

ToastKind

Controls icon, haptic feedback, and default display duration.

Case Icon Default Duration
.success checkmark.circle.fill 3s
.info info.circle.fill 3s
.warning exclamationmark.circle.fill 4s
.error xmark.circle.fill 4s

ToastDuration

Value Duration
.default Kind-appropriate (see above)
.short 2 seconds
.standard 3.5 seconds
.long 5 seconds
.indefinite No auto-dismiss
.custom(_ seconds:) 1–8 seconds (clamped)

ToastPosition

Case Description
.bottom Above home indicator (default)
.center Vertically centered
.top Below status bar

ToastItem

ToastItem(
    kind: .success,
    title: "File saved",
    subtitle: "Tap to open",          // optional
    iconName: "square.and.arrow.up",  // nil = kind default, "" = suppress icon
    duration: .standard,
    position: .bottom,
    tapToDismiss: true
)

SwiftUI Modifiers

Modifier Description
.toastHost() Installs toast infrastructure — call once at scene root
.toast(item:) Presents a toast when binding becomes non-nil
@Environment(\.toastManager) Access the scene-bound manager from any view

Architecture

Toast uses a UIWindowScene-backed overlay window sitting above the key window. This ensures toasts appear over sheets, full-screen covers, and navigation stacks — something pure SwiftUI overlay modifiers cannot guarantee.

A Swift actor-isolated queue serializes all enqueue, dismiss, and timer operations, eliminating concurrency bugs between auto-dismiss timers and rapid-fire enqueue events.

Key behaviors:

  • FIFO queueing — multiple toasts are shown in order, one at a time
  • Deduplication — identical consecutive toasts refresh the timer instead of stacking
  • Safe area awareness — respects Dynamic Island, home indicator, and keyboard
  • Hit-test pass-through — touches outside the toast reach your app normally
  • Accessibility — VoiceOver announcements, Reduce Motion support, semantic traits
  • HapticsUINotificationFeedbackGenerator feedback per kind

Multi-Scene Support

For apps with multiple UIWindowScene instances, use the per-scene API:

// In your SceneDelegate or scene-lifecycle handler:
let manager = ToastManager.manager(for: windowScene)
manager.show(.info, title: "Scene-specific toast")

// Clean up when the scene disconnects:
ToastManager.removeManager(for: windowScene)

License

Toast is available under the MIT license. See LICENSE for details.

About

A production-ready iOS toast notification library

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages