jaywcjlove/toast
Toast
β¨ Features
- π― Simple API - Clean, intuitive interface:
Toast.success("Hello!") - β‘ High Performance - Smooth animations and optimized memory usage
- π Flexible Positioning - Multiple positioning options (top, bottom, center)
- π¨ Customizable - Theming, styling, and configuration support
- π Promise Support - Built-in async operation handling
- π± SwiftUI Native - Perfect integration with SwiftUI environment
π Quick Start
1. Installation
// Package.swift
dependencies: [
.package(url: "https://github.com/jaywcjlove/Toast.git", from: "1.0.0")
]2. Setup
Enable Toast in your app:
import SwiftUI
import Toast
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.toast() // Enable toast container
}
}
}3. Basic Usage
import Toast
struct ContentView: View {
var body: some View {
VStack {
Button("Success") {
// Static API (recommended)
Toast.success("Operation completed!")
}
Button("Error") {
Toast.error("Something went wrong")
}
Button("Info") {
Toast.info("Just so you know")
}
Button("Loading") {
Toast.loading("Processing...")
}
Button("Clear") {
Toast.dismissAll()
}
}
.toast() // Enable toast container
}
}API Reference
Basic Messages
// Method 1: Static API (works everywhere)
Toast.success("Success message")
Toast.error("Error message")
Toast.info("Info message")
Toast.loading("Loading message")
// Method 2: Full API (advanced usage)
ToastManager.shared.success("Success!")
ToastManager.shared.error("Error occurred")
ToastManager.shared.info("Information")
ToastManager.shared.loading("Loading...")Positioning
// Available positions
Toast.success("Message", position: .topLeft)
Toast.info("Message", position: .topCenter) // default
Toast.error("Message", position: .topRight)
Toast.success("Message", position: .bottomLeft)
Toast.info("Message", position: .bottomCenter)
Toast.error("Message", position: .bottomRight)
Toast.loading("Message", position: .center)Custom Toasts
// Custom SwiftUI content
Toast.custom {
HStack {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("Custom message")
.fontWeight(.bold)
}
.padding()
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(8)
}Promise Support
Automatic async operation state handling:
Toast.promise(
operation: {
// Your async operation
try await Task.sleep(for: .seconds(2))
return "Upload completed"
},
messages: .init(
loading: "Uploading...",
success: "Upload successful!",
error: "Upload failed"
)
)Configuration
// Global configuration
ToastManager.shared.configuration.duration = 5.0
ToastManager.shared.configuration.position = .topCenter
// Per-toast configuration
// β οΈ Static API doesn't support duration parameter
// Use ToastManager for custom duration:
ToastManager.shared.success("Custom duration", duration: 8.0)
ToastManager.shared.info("Manual dismiss", duration: 0) // Never auto-dismissControl Methods
// Dismiss toasts
Toast.dismiss() // Dismiss latest toast
Toast.dismissAll() // Dismiss all toasts
// For ID-specific operations, use ToastManager:
ToastManager.shared.info("Loading...", id: "specific-id")
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
Toast.dismiss(id: "specific-id") // Dismiss by ID
}Complete Example
import SwiftUI
import Toast
struct ContentView: View {
@State private var counter = 0
var body: some View {
VStack(spacing: 20) {
Text("Toast Demo")
.font(.largeTitle)
// Basic toast types
HStack {
Button("Success") {
counter += 1
Toast.success("Success #\(counter)")
}
Button("Error") {
Toast.error("Something went wrong")
}
Button("Info") {
Toast.info("Information message")
}
}
// Loading and promise
Button("Loading") {
Toast.loading("Processing...")
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
Toast.success("Done!")
}
}
// Async promise
Button("Async Task") {
Toast.promise(
operation: {
try await Task.sleep(for: .seconds(2))
return "Task completed"
},
messages: .init(
loading: "Working...",
success: "Finished!",
error: "Failed"
)
)
}
// Custom toast
Button("Custom") {
Toast.custom {
HStack {
Image(systemName: "star.fill")
.foregroundColor(.yellow)
Text("Custom Toast")
}
.padding()
.background(Color.purple)
.foregroundColor(.white)
.cornerRadius(8)
}
}
// Clear all
Button("Clear All") {
Toast.dismissAll()
}
.foregroundColor(.red)
}
.padding()
.toast() // Enable toast container
}
}Troubleshooting
"Use of 'toast' refers to instance method" Error
This error occurs due to naming conflict between the global toast instance and the .toast() modifier method.
β Problem:
struct MyView: View {
var body: some View {
Button("Test") {
toast.success("Hello") // Error: naming conflict
}
.toast() // This creates the conflict
}
}β Solution (Recommended):
Use Static API (always works)
Button("Test") {
Toast.success("Hello") // β
Always reliable
}Alternative Solutions:
// Method 1: ToastManager directly
Button("Test") {
ToastManager.shared.success("Hello") // β
Always works
}
// Method 2: Only in completely separate contexts
class SomeService {
func performAction() {
// β
Works in non-SwiftUI contexts
toast.success("Service action completed")
}
}Configuration Options
struct ToastConfiguration {
var position: ToastPosition = .topCenter
var duration: TimeInterval = 3.0
var theme: ToastTheme = .system
var maxVisibleToasts: Int = 3
var animationDuration: TimeInterval = 0.3
var spacing: CGFloat = 8
}License
Licensed under the MIT License.
Package Metadata
Repository: jaywcjlove/toast
Default branch: main
README: README.md