Toast Notification System
An elegant, non-intrusive notification system that provides instant feedback for user actions. Includes automatic notifications for cart operations and a flexible API for custom messages.
Overview
The Toast Notification system consists of three main components:
RToastNotification
- Individual toast message with animationsToastManager
- Global singleton for managing notificationsRToastOverlay
- Global overlay that displays toasts app-wide
This system automatically provides notifications for cart operations and can be used for any custom user feedback needs.
Key Features
- ✅ Automatic Cart Notifications - Shows when products are added/removed
- ✅ Multiple Types - Success, info, warning, error variants
- ✅ Product Names - Includes specific product information
- ✅ Auto-dismiss - Disappears automatically with smooth animations
- ✅ Haptic Feedback - Tactile confirmation on iOS devices
- ✅ Global Management - Single API for all notifications
- ✅ Elegant Design - Professional appearance with blur effects
- ✅ Cross-platform - Works on iOS, macOS, tvOS, and watchOS
Basic Setup
Global Toast Overlay
Add the toast overlay to your main app structure:
import SwiftUI
import ReachuUI
@main
struct MyApp: App {
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(CartManager())
.overlay {
RToastOverlay() // Global toast system
}
}
}
}
Alternative: Per-Screen Integration
You can also add toast overlay to specific screens:
import SwiftUI
import ReachuUI
struct ContentView: View {
var body: some View {
NavigationView {
YourMainContent()
}
.overlay {
RToastOverlay() // Toast overlay for this screen
}
}
}
Automatic Cart Notifications
When you use CartManager
, toast notifications appear automatically:
Automatic Triggers
// Adding a product triggers success toast
await cartManager.addProduct(product)
// 🟢 Toast: "Added Wireless Headphones to cart"
// Removing a product triggers info toast
await cartManager.removeItem(cartItem)
// 🔵 Toast: "Removed Wireless Headphones from cart"
// Updating quantity triggers success toast
await cartManager.updateQuantity(for: item, to: 3)
// 🟢 Toast: "Updated Wireless Headphones quantity in cart"
What You Get Automatically
- Product Name - Specific product included in message
- Appropriate Type - Success for add, info for remove
- Haptic Feedback - Tactile confirmation on iOS
- Auto-dismiss - Disappears after 3 seconds
- Non-intrusive - Appears at top, doesn't block content
Manual Toast Notifications
Use ToastManager
for custom notifications throughout your app:
Basic Usage
import ReachuUI
// Success notification
ToastManager.shared.showSuccess("Product added to wishlist!")
// Error notification
ToastManager.shared.showError("Failed to load product details")
// Info notification
ToastManager.shared.showInfo("Profile updated successfully")
// Warning notification
ToastManager.shared.showWarning("Low stock - only 2 items remaining")
Advanced Configuration
// Custom duration (default is 3.0 seconds)
ToastManager.shared.show(
"Custom message",
type: .success,
duration: 5.0
)
// Manual dismiss
ToastManager.shared.dismiss()
Toast Types
Success Toasts
ToastManager.shared.showSuccess("Product added to cart!")
ToastManager.shared.showSuccess("Order placed successfully")
ToastManager.shared.showSuccess("Payment processed")
Visual Style:
- 🟢 Green checkmark icon
- ✅ Success color scheme
- 📳 Success haptic feedback
Error Toasts
ToastManager.shared.showError("Network connection failed")
ToastManager.shared.showError("Invalid product quantity")
ToastManager.shared.showError("Payment processing failed")
Visual Style:
- 🔴 Red X icon
- ❌ Error color scheme
- 📳 Error haptic feedback
Info Toasts
ToastManager.shared.showInfo("Product removed from cart")
ToastManager.shared.showInfo("Search results updated")
ToastManager.shared.showInfo("Profile synchronized")
Visual Style:
- 🔵 Blue info icon
- ℹ️ Info color scheme
- 📳 Light haptic feedback
Warning Toasts
ToastManager.shared.showWarning("Low stock remaining")
ToastManager.shared.showWarning("Session will expire soon")
ToastManager.shared.showWarning("Large file upload")
Visual Style:
- 🟡 Yellow warning icon
- ⚠️ Warning color scheme
- 📳 Warning haptic feedback
Real-World Examples
E-commerce Operations
class ShoppingActions {
func addToWishlist(_ product: Product) async {
do {
try await wishlistService.add(product)
ToastManager.shared.showSuccess("Added \(product.title) to wishlist")
} catch {
ToastManager.shared.showError("Failed to add to wishlist")
}
}
func applyDiscount(code: String) async {
do {
let discount = try await discountService.apply(code)
ToastManager.shared.showSuccess("Applied \(discount.title) - Save \(discount.amount)%")
} catch {
ToastManager.shared.showError("Invalid discount code")
}
}
func checkStock(_ product: Product) async {
let stock = await stockService.check(product.id)
if stock < 5 {
ToastManager.shared.showWarning("Only \(stock) items left in stock")
}
}
}
User Profile Operations
class ProfileActions {
func updateProfile(_ profile: UserProfile) async {
do {
try await profileService.update(profile)
ToastManager.shared.showSuccess("Profile updated successfully")
} catch {
ToastManager.shared.showError("Failed to update profile")
}
}
func uploadAvatar(_ image: UIImage) async {
do {
try await avatarService.upload(image)
ToastManager.shared.showSuccess("Avatar updated")
} catch {
ToastManager.shared.showError("Failed to upload avatar")
}
}
func syncData() async {
do {
try await syncService.synchronize()
ToastManager.shared.showInfo("Data synchronized")
} catch {
ToastManager.shared.showWarning("Sync failed - will retry later")
}
}
}
Form Validation
struct ContactForm: View {
@State private var email = ""
@State private var message = ""
var body: some View {
VStack {
TextField("Email", text: $email)
TextEditor(text: $message)
Button("Send Message") {
if validateForm() {
submitForm()
}
}
}
}
private func validateForm() -> Bool {
if email.isEmpty {
ToastManager.shared.showError("Email is required")
return false
}
if !email.contains("@") {
ToastManager.shared.showError("Invalid email format")
return false
}
if message.count < 10 {
ToastManager.shared.showWarning("Message too short (minimum 10 characters)")
return false
}
return true
}
private func submitForm() {
ToastManager.shared.showSuccess("Message sent successfully!")
}
}
Design & Styling
Visual Design
Toast notifications feature:
- Blur Background - Ultra-thin material for elegant appearance
- Shadow - Subtle drop shadow for depth
- Rounded Corners - Large border radius for modern look
- Color Coordination - Icons and colors match message type
- Typography - Clear, readable text with proper hierarchy
Animation Specifications
// Appear animation
.offset(y: -100) → .offset(y: 0)
.opacity(0) → .opacity(1)
.spring(response: 0.6, dampingFraction: 0.8)
// Dismiss animation
.offset(y: 0) → .offset(y: -100)
.opacity(1) → .opacity(0)
.easeInOut(duration: 0.3)
// Auto-dismiss timing
DispatchQueue.main.asyncAfter(deadline: .now() + duration) {
dismissToast()
}
Layout Specifications
// Container
.padding(ReachuSpacing.md) // 16pt padding
.background(.ultraThinMaterial) // Blur background
.cornerRadius(ReachuBorderRadius.large) // 12pt corner radius
.shadow(color: .black.opacity(0.1), radius: 8, x: 0, y: 4)
// Content spacing
HStack(spacing: ReachuSpacing.sm) // 12pt between icon and text
// Positioning
VStack { /* content at top */ Spacer() } // Top positioning
.padding(.horizontal, ReachuSpacing.lg) // 24pt side margins
.padding(.top, ReachuSpacing.sm) // 12pt top margin
Advanced Features
Custom Toast Component
You can create custom toast notifications with specific styling:
struct CustomToast: View {
let message: String
@Binding var isPresented: Bool
var body: some View {
RToastNotification(
message: message,
type: .success,
duration: 2.0,
isPresented: $isPresented
)
}
}
// Usage
@State private var showCustomToast = false
Button("Show Custom Toast") {
showCustomToast = true
}
.overlay {
if showCustomToast {
CustomToast(
message: "Custom notification message",
isPresented: $showCustomToast
)
}
}
Conditional Notifications
class NotificationSettings: ObservableObject {
@Published var cartNotificationsEnabled = true
@Published var errorNotificationsEnabled = true
@Published var infoNotificationsEnabled = false
}
// In your CartManager
if notificationSettings.cartNotificationsEnabled {
ToastManager.shared.showSuccess("Added \(product.title) to cart")
}
Queue Management
The toast system automatically manages notification queues:
// Multiple rapid notifications
ToastManager.shared.showSuccess("First message")
ToastManager.shared.showInfo("Second message") // Replaces first
ToastManager.shared.showError("Third message") // Replaces second
// Current behavior: Only one toast shown at a time
// New toasts replace existing ones
Accessibility
Toast notifications include comprehensive accessibility support:
// Automatic screen reader announcements
.accessibilityLabel("Notification: \(message)")
// Message type identification
.accessibilityValue("Success notification") // or Error, Info, Warning
// Action availability
.accessibilityHint("Notification will dismiss automatically")
// Dismiss button
.accessibilityLabel("Dismiss notification")
.accessibilityAddTraits(.isButton)
Platform-Specific Behavior
iOS
- Haptic Feedback - Different patterns for each notification type
- Dynamic Type - Automatically adjusts text size
- Safe Areas - Respects notch and home indicator
macOS
- Notification Center - Integrates with system notification patterns
- Mouse Interaction - Proper hover states and click handling
- Window Management - Appears above content without blocking
tvOS
- Focus Management - Doesn't interfere with focus navigation
- Remote Control - Can be dismissed with remote
- Screen Size - Appropriate sizing for TV displays
watchOS
- Simplified Design - Reduced information for small screens
- Wrist Tap - Uses watch haptics when available
- Quick Dismiss - Shorter default duration for watch usage
Performance Optimization
Efficient Rendering
- ✅ Single Instance - Only one toast rendered at a time
- ✅ Conditional Rendering - Only appears when needed
- ✅ Animation Optimization - Hardware-accelerated animations
- ✅ Memory Management - Automatic cleanup when dismissed
Best Practices
- Use Appropriate Types - Match notification type to message severity
- Keep Messages Short - Aim for one line of text when possible
- Avoid Spam - Don't show multiple toasts in rapid succession
- Test on Devices - Verify haptic feedback and animations
- Consider Context - Use toasts for non-critical information only
Integration Guidelines
With Cart System
// Automatic - no additional code needed
await cartManager.addProduct(product) // Auto-shows toast
// Manual override if needed
await cartManager.addProduct(product, showToast: false)
ToastManager.shared.showSuccess("Custom cart message")
With Error Handling
do {
try await performOperation()
ToastManager.shared.showSuccess("Operation completed")
} catch NetworkError.noConnection {
ToastManager.shared.showError("No internet connection")
} catch NetworkError.timeout {
ToastManager.shared.showWarning("Request timed out - please try again")
} catch {
ToastManager.shared.showError("An unexpected error occurred")
}
With Loading States
class DataLoader: ObservableObject {
@Published var isLoading = false
func loadData() async {
isLoading = true
defer { isLoading = false }
do {
let data = try await dataService.fetch()
ToastManager.shared.showSuccess("Data loaded successfully")
} catch {
ToastManager.shared.showError("Failed to load data")
}
}
}
Toast notifications work best when used sparingly for important feedback. Use success toasts for confirmations, error toasts for failures, info toasts for updates, and warning toasts for important notices.
When you use CartManager
with the toast system, notifications appear automatically for all cart operations. You don't need to manually trigger them for standard cart actions.