ToastKit is a small SwiftUI toast presenter for iOS and macOS apps. It shows lightweight status messages in a dedicated presentation window, supports blocking modal overlays, and lets users drag the toast up or down to dismiss it.
- iOS 16.0+ or macOS 13.0+
- Swift 6.0+
- SwiftUI (UIKit on iOS; AppKit on macOS)
- Xcode with the corresponding iOS or macOS SDK
ToastKit builds with iOS 16 and macOS 13 deployment targets. On newer SDKs it can use the modern glass surface branch when available, while older runtime versions fall back to a colored SwiftUI surface.
Add ToastKit with Swift Package Manager:
dependencies: [
.package(url: "https://github.com/Horse888/ToastKit.git", from: "1.0.0")
]Then add ToastKit to your app target dependencies and import it where you present toasts:
import ToastKitShow a built-in toast:
ToastKit.show(
ToastInfo(type: .success, msg: "Saved"),
duration: 3
)Built-in success, warning, error, and loading toasts show a default SF Symbol automatically. On iOS 17 and later, the symbol also uses SwiftUI symbol effects when it appears; iOS 16 shows a static symbol.
Show an error:
ToastKit.showError("Something went wrong")Hide the current toast manually:
ToastKit.hide()Use duration: 0 when the toast should stay visible until you hide it:
ToastKit.show(
ToastInfo(type: .loading(.accentColor), msg: "Syncing..."),
duration: 0
)Non-modal mode is the default. The toast floats above your app and taps outside the toast continue to pass through to the underlying UI:
ToastKit.show(
ToastInfo(type: .success, msg: "Copied"),
isModal: false
)Modal mode adds a dimming overlay and blocks interaction with the underlying UI:
ToastKit.show(
ToastInfo(type: .warning, msg: "Please wait"),
duration: 2,
isModal: true
)Both modes support drag interaction. Drag the toast up or down far enough to dismiss it. While the user is dragging, automatic dismissal pauses; if the drag is cancelled before the threshold, the timer resumes.
ToastInfo(type: .success, msg: "Done")
ToastInfo(type: .warning, msg: "Network unstable")
ToastInfo(type: .error, msg: "Save failed")
ToastInfo(type: .loading(.blue), msg: "Uploading")Default symbols:
.success:checkmark.circle.fill.warning:exclamationmark.triangle.fill.error:xmark.octagon.fill.loading:arrow.triangle.2.circlepath
Override the SF Symbol for any built-in toast:
ToastKit.show(
ToastInfo(
type: .success,
msg: "Added to favorites",
sfSymbolName: "star.fill"
)
)Pass nil explicitly to hide the SF Symbol:
ToastKit.show(
ToastInfo(type: .success, msg: "Saved", sfSymbolName: nil)
)You can present any SwiftUI view:
ToastKit.show(duration: 4, isModal: false) {
HStack(spacing: 12) {
Image(systemName: "icloud.and.arrow.up")
VStack(alignment: .leading, spacing: 2) {
Text("Upload complete")
.font(.headline)
Text("12 files were backed up")
.font(.caption)
.foregroundStyle(.secondary)
}
}
.padding(.horizontal, 18)
.padding(.vertical, 12)
.background(.regularMaterial, in: Capsule())
}ToastKit applies the presentation, drag, timer, and modal behavior. Your custom view controls its own layout and visual styling.
Configure the default CommonToast style once, usually at app startup:
ToastKit.configure(
style: ToastStyle(
successBackgroundColor: .green.opacity(0.14),
warningBackgroundColor: .orange.opacity(0.14),
errorBackgroundColor: .red.opacity(0.14),
loadingBackgroundColor: .blue.opacity(0.14),
foregroundColor: .primary,
font: .system(size: 15, weight: .semibold),
symbolFont: .system(size: 22, weight: .bold),
monospacedDigits: true,
horizontalPadding: 22,
verticalPadding: 12,
contentHorizontalPadding: 24,
maxWidth: 450,
topPadding: 14,
cornerRadius: 999,
shadowRadius: 24,
shadowY: 5,
modalOverlayColor: .black.opacity(0.18),
animationDuration: 0.3,
hapticFeedbackEnabled: true
)
)Available style options:
- Background colors for success, warning, error, and loading states
- Border colors for success, warning, error, and loading states
- Text color, text font, SF Symbol font, and monospaced-digit setting (enabled by default)
- Light appearance haptic feedback on iOS (enabled by default)
- Horizontal and vertical content padding
- Top spacing and screen-edge padding
- Corner radius, border width, and shadow
- Modal overlay color
- Presentation animation duration
- ToastKit presents from the best available foreground
UIWindowSceneon iOS, and from a dedicated floatingNSWindowon macOS. - Showing a new toast replaces the current toast and resets the dismissal timer. Consecutive loading updates replace the current loading toast in place.
- Toasts enter from above the screen, using a notification-style drop animation.
ToastKit.showErrorlogs the error message throughOSLog.- Non-modal mode only captures touches inside the toast hit area; the rest of the overlay window passes touches through.
- Drag dismissal reports
.dragUpor.dragDowninternally, and programmatic dismissal uses.programmatic.
Build the package target for iOS from the command line:
swift build --sdk /path/to/iPhoneOS.sdk --triple arm64-apple-ios16.0Build and test the macOS package target with standard SwiftPM commands:
swift build
swift testThe iOS target should be built with an iPhoneOS SDK and triple, as shown above.
Open the lightweight example project:
open Examples/ToastKitDemo/ToastKitDemo.xcodeprojSelect the ToastKitDemo scheme to run a real app on an iOS Simulator or on macOS. The project references this repository as a local Swift package, so the package source under Sources/ToastKit remains directly editable from Xcode while the demo is running.
The demo interface and its SwiftUI previews live entirely inside the example Xcode project. They are not package products and are not compiled or linked when an app depends on ToastKit.
To record a GIF:
xcrun simctl io booted recordVideo /tmp/toastkit-demo.movLaunch the demo while recording, stop recording with Control-C, then convert it:
ffmpeg -y -i /tmp/toastkit-demo.mov \
-vf 'fps=12,scale=320:-1:flags=lanczos,split[s0][s1];[s0]palettegen=max_colors=96[p];[s1][p]paletteuse=dither=bayer:bayer_scale=5' \
Documentation/Images/toastkit-demo.gifToastKit is available under the MIT license. See LICENSE for details.



