import SwiftUI struct ToastView: View { let message: String let isSuccess: Bool var body: some View { HStack(spacing: 12) { Image(systemName: isSuccess ? "checkmark.circle.fill" : "xmark.circle.fill") .font(.title3) .foregroundColor(isSuccess ? Color(hex: "00d4aa") : Color(hex: "ff4757")) Text(message) .font(.subheadline.weight(.medium)) .foregroundColor(.white) .lineLimit(2) Spacer() } .padding(.horizontal, 20) .padding(.vertical, 14) .background( RoundedRectangle(cornerRadius: 16) .fill(.ultraThinMaterial) .overlay( RoundedRectangle(cornerRadius: 16) .stroke( (isSuccess ? Color(hex: "00d4aa") : Color(hex: "ff4757")).opacity(0.3), lineWidth: 1 ) ) ) .shadow(color: .black.opacity(0.3), radius: 10, y: 5) .padding(.horizontal, 20) } } // MARK: - Toast Modifier struct ToastModifier: ViewModifier { @Binding var isShowing: Bool let message: String let isSuccess: Bool func body(content: Content) -> some View { ZStack(alignment: .bottom) { content if isShowing { ToastView(message: message, isSuccess: isSuccess) .padding(.bottom, 40) .transition(.move(edge: .bottom).combined(with: .opacity)) .zIndex(100) .onAppear { DispatchQueue.main.asyncAfter(deadline: .now() + 3) { withAnimation(.easeInOut(duration: 0.3)) { isShowing = false } } } } } .animation(.spring(response: 0.4, dampingFraction: 0.8), value: isShowing) } } extension View { func toast(isShowing: Binding, message: String, isSuccess: Bool) -> some View { modifier(ToastModifier(isShowing: isShowing, message: message, isSuccess: isSuccess)) } }