Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[CAT-198] Toast #30

Merged
merged 2 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// ToastDetailView.swift
// DesignSystemExample
//
// Created by devMinseok on 8/16/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import SwiftUI

import DesignSystem

struct ToastDetailView: View {
@State var toast: DefaultToast?

var body: some View {
VStack {
Button {
toast = DefaultToast(message: "Thist is test message for toast", image: Image(systemName: "left"))
} label: {
Text("showToast")
}
}
.toastDestination(toast: $toast)
}
}

#Preview {
ToastDetailView()
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ struct ContentView: View {
Text("BottomSheet")
}

NavigationLink {
ToastDetailView()
} label: {
Text("Toast")
}

NavigationLink {

} label: {
Expand All @@ -69,7 +75,7 @@ struct ContentView: View {
NavigationLink {

} label: {
Text("Toast")
Text("TextField")
devMinseok marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,24 @@

import SwiftUI

extension View {
public func bottomSheet<
Item: Identifiable,
Content: View
>(
item: Binding<Item?>,
@ViewBuilder content: @escaping (Item) -> Content
) -> some View {
struct BottomSheetViewModifier<
Item: Identifiable,
BottomSheetContent: View
>: ViewModifier {
@Binding var item: Item?
let bottomSheetContent: (Item) -> BottomSheetContent

func body(content: Content) -> some View {
ZStack(alignment: .bottom) {
self
content
.frame(maxWidth: .infinity, maxHeight: .infinity)
.zIndex(1)

if let wrappedItem = item.wrappedValue {
if let item {
Global.Color.black.opacity(Global.Opacity._50d)
.ignoresSafeArea()
.onTapGesture {
item.wrappedValue = nil
self.item = nil
}
.transition(
.opacity.animation(.easeInOut)
Expand All @@ -44,24 +45,34 @@ extension View {
DragGesture(minimumDistance: 20)
.onEnded { value in
if value.translation.height > 100 {
withAnimation {
item.wrappedValue = nil
}
self.item = nil
}
}
)

content(wrappedItem)
bottomSheetContent(item)
.frame(maxWidth: .infinity)
.fixedSize(horizontal: false, vertical: true)
.background(Global.Color.white)
}
.frame(maxWidth: .infinity)
.frame(maxHeight: UIScreen.main.bounds.height * 0.9, alignment: .bottom)
.transition(.move(edge: .bottom))
.animation(.spring(duration: 0.4))
.zIndex(3)
}
}
.animation(.spring(duration: 0.4), value: self.item == nil)
}
}

extension View {
public func bottomSheet<
Item: Identifiable,
Content: View
>(
item: Binding<Item?>,
@ViewBuilder content: @escaping (Item) -> Content
) -> some View {
return self.modifier(BottomSheetViewModifier(item: item, bottomSheetContent: content))
}
}
30 changes: 30 additions & 0 deletions Projects/Shared/DesignSystem/Sources/Component/Toast/Toast.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//
// Toast.swift
// DesignSystem
//
// Created by devMinseok on 8/16/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import SwiftUI

public protocol Toast: Equatable {
var message: String { get }
var image: Image? { get }
var hideAutomatically: Bool { get }
}

public struct DefaultToast: Toast {
public let message: String
public let image: Image?
public let hideAutomatically: Bool

public init(
message: String,
image: Image
) {
self.message = message
self.image = image
hideAutomatically = true
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// ToastView.swift
// DesignSystem
//
// Created by devMinseok on 8/16/24.
// Copyright © 2024 PomoNyang. All rights reserved.
//

import SwiftUI

struct ToastViewModifier<T: Toast>: ViewModifier {
@Binding var toast: T?

init(toast: Binding<T?>) {
_toast = toast
}

func body(content: Content) -> some View {
ZStack(alignment: .bottom ) {
content
.frame(maxWidth: .infinity, maxHeight: .infinity)
.zIndex(1)

if let toast {
HStack(alignment: .center, spacing: 8) {
if let image = toast.image {
image
}
Text(toast.message)
.foregroundStyle(Global.Color.white)
.font(Typography.subBodyR)
.multilineTextAlignment(.leading)
.frame(maxWidth: .infinity, alignment: .leading)
}
.padding(16)
.background(
RoundedRectangle(cornerRadius: 16)
.fill(Alias.Color.Background.inverse)
.opacity(Global.Opacity._90d)
)
.padding(.horizontal, Global.Dimension._20f)
.transition(
.move(edge: .bottom)
.combined(with: .opacity.animation(.easeInOut))
)
.onAppear {
if toast.hideAutomatically {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
if self.toast != nil {
self.toast = nil
}
}
}
}
.onTapGesture {
self.toast = nil
}
.zIndex(2)
}
}
.animation(.spring(duration: 0.3), value: self.toast)
}
}

extension View {
public func toastDestination<T: Toast>(
toast: Binding<T?>
) -> some View {
self.modifier(ToastViewModifier(toast: toast))
}
}
Loading