diff --git a/SemicolonDesign/Sources/BottomSheet/Preview/SDBottomSheetPreview.swift b/SemicolonDesign/Sources/BottomSheet/Preview/SDBottomSheetPreview.swift new file mode 100644 index 000000000..c2a3fd17c --- /dev/null +++ b/SemicolonDesign/Sources/BottomSheet/Preview/SDBottomSheetPreview.swift @@ -0,0 +1,17 @@ +import SwiftUI + +struct SDBottomSheetPreview: View { + @State var isPresented: Bool = false + var body: some View { + Button { + isPresented = true + } label: { + Text("Test BottomSheet") + } + .sdBottomSheet(isPresented: $isPresented, buttons: [ + (text: "수정하기", action: { print("!!!!!") }), + (text: "삭제하기", action: { print("반가워요") }) + ]) + } +} + diff --git a/SemicolonDesign/Sources/BottomSheet/SDBottomSheet.swift b/SemicolonDesign/Sources/BottomSheet/SDBottomSheet.swift new file mode 100644 index 000000000..b4930664f --- /dev/null +++ b/SemicolonDesign/Sources/BottomSheet/SDBottomSheet.swift @@ -0,0 +1,43 @@ +import SwiftUI + +struct SDBottomSheet: View { + @Binding var isPresented: Bool + var buttons: [(text: String, action: () -> Void)] + + init( + isPresented: Binding, + buttons: [(text: String, action: () -> Void)] + ) { + self.buttons = buttons + self._isPresented = isPresented + } + + var body: some View { + VStack(alignment: .leading, spacing: 0) { + ForEach(buttons, id: \.text) { button in + Button{ + self.isPresented = false + button.action() + } label: { + HStack { + Text(button.text) + Spacer() + } + } + .padding(.bottom, 26) + } + } + .foregroundColor(.black) + .padding(.leading, 29) + .padding(.top, 36) + .padding(.bottom, 4) + .background(Color.white) + .cornerRadius(16, [.topLeft, .topRight]) + } +} + +struct SwiftUIView_Previews: PreviewProvider { + static var previews: some View { + SDBottomSheetPreview() + } +} diff --git a/SemicolonDesign/Sources/BottomSheet/SDBottomSheetModifier.swift b/SemicolonDesign/Sources/BottomSheet/SDBottomSheetModifier.swift new file mode 100644 index 000000000..9082e71a2 --- /dev/null +++ b/SemicolonDesign/Sources/BottomSheet/SDBottomSheetModifier.swift @@ -0,0 +1,28 @@ +import SwiftUI + +struct SDBottomSheetModifier: ViewModifier { + + var isPresented: Binding + var buttons: [(text: String, action: () -> Void)] + + func body(content: Content) -> some View { + ZStack { + content + if isPresented.wrappedValue { + Color.black.opacity(0.4) + .ignoresSafeArea() + VStack { + Spacer() + Color.white + .edgesIgnoringSafeArea(.bottom) + .frame(height: CGFloat(40)) + } + VStack(spacing: 0) { + Spacer() + SDBottomSheet(isPresented: isPresented, buttons: buttons) + } + .animation(.easeOut, value: isPresented.wrappedValue) + } + } + } +} diff --git a/SemicolonDesign/Sources/BottomSheet/View+sdBottomSheet.swift b/SemicolonDesign/Sources/BottomSheet/View+sdBottomSheet.swift new file mode 100644 index 000000000..1ddb0dbae --- /dev/null +++ b/SemicolonDesign/Sources/BottomSheet/View+sdBottomSheet.swift @@ -0,0 +1,7 @@ +import SwiftUI + +public extension View { + func sdBottomSheet(isPresented: Binding, buttons: [(text: String, action: () -> Void)]) -> some View { + self.modifier(SDBottomSheetModifier(isPresented: isPresented, buttons: buttons)) + } +} diff --git a/SemicolonDesign/Sources/Extension/View+cornerRadius.swift b/SemicolonDesign/Sources/Extension/View+cornerRadius.swift new file mode 100644 index 000000000..49e822b0d --- /dev/null +++ b/SemicolonDesign/Sources/Extension/View+cornerRadius.swift @@ -0,0 +1,23 @@ +import SwiftUI + +extension View { + func cornerRadius(_ radius: CGFloat, _ corners: UIRectCorner) -> some View { + clipShape(RoundedCorner(radius: radius, corners: corners)) + } +} + +struct RoundedCorner: Shape { + + var radius: CGFloat = .infinity + var corners: UIRectCorner = .allCorners + + func path(in rect: CGRect) -> Path { + let path = UIBezierPath( + roundedRect: rect, + byRoundingCorners: corners, + cornerRadii: CGSize(width: radius, height: radius) + ) + return Path(path.cgPath) + } + +}