diff --git a/Projects/Shared/DesignSystem/Example/Sources/Component/BottomSheetDetailView.swift b/Projects/Shared/DesignSystem/Example/Sources/Component/BottomSheetDetailView.swift new file mode 100644 index 0000000..371b107 --- /dev/null +++ b/Projects/Shared/DesignSystem/Example/Sources/Component/BottomSheetDetailView.swift @@ -0,0 +1,74 @@ +// +// BottomSheetDetailView.swift +// DesignSystemExample +// +// Created by devMinseok on 8/12/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +import DesignSystem + +enum BottomSheetColor: Identifiable { + var id: Self { self } + + case red + case green + case blue +} + +struct BottomSheetDetailView: View { + @State var bottomSheet: BottomSheetColor? + + var body: some View { + VStack(spacing: 10) { + Spacer() + Button { + bottomSheet = .red + } label: { + Text("red bottom sheet") + } + Button { + bottomSheet = .green + } label: { + Text("green bottom sheet") + } + Button { + bottomSheet = .blue + } label: { + Text("blue bottom sheet") + } + Spacer() + } + .bottomSheet(item: $bottomSheet) { item in + BottomSheetChildView(color: item) + } + } +} + +#Preview { + BottomSheetDetailView() +} + +struct BottomSheetChildView: View { + let color: BottomSheetColor + + var body: some View { + ScrollView { + VStack { + switch color { + case .red: + Color.red + .frame(height: 400) + case .green: + Color.green + .frame(height: 400) + case .blue: + Color.blue + .frame(height: 400) + } + } + } + } +} diff --git a/Projects/Shared/DesignSystem/Example/Sources/Component/ButtonDetailView.swift b/Projects/Shared/DesignSystem/Example/Sources/Component/ButtonDetailView.swift index 95d37ac..ca91c33 100644 --- a/Projects/Shared/DesignSystem/Example/Sources/Component/ButtonDetailView.swift +++ b/Projects/Shared/DesignSystem/Example/Sources/Component/ButtonDetailView.swift @@ -209,6 +209,52 @@ struct ButtonDetailView: View { .padding(.horizontal, 20) } } + + VStack(spacing: 40) { + Text("Icon") + .font(.title) + HStack { + Button( + icon: Image(systemName: "left"), + action: { /*action*/ } + ) + .buttonStyle(.icon(isFilled: false, level: .primary)) + Button( + icon: Image(systemName: "right"), + action: { /*action*/ } + ) + .buttonStyle(.icon(isFilled: true, level: .primary)) + Button( + icon: Image(systemName: "left"), + action: { /*action*/ } + ) + .buttonStyle(.icon(isFilled: false, level: .primary)) + .disabled(true) + Button( + icon: Image(systemName: "right"), + action: { /*action*/ } + ) + .buttonStyle(.icon(isFilled: true, level: .primary)) + .disabled(true) + } + } + + VStack(spacing: 40) { + Text("Round") + .font(.title) + HStack { + Button( + icon: Image(systemName: "left"), + action: { /*action*/ } + ) + .buttonStyle(.round(level: .primary)) + Button( + icon: Image(systemName: "right"), + action: { /*action*/ } + ) + .buttonStyle(.round(level: .secondary)) + } + } } } } diff --git a/Projects/Shared/DesignSystem/Example/Sources/ContentView.swift b/Projects/Shared/DesignSystem/Example/Sources/ContentView.swift index 569cb00..a41de69 100644 --- a/Projects/Shared/DesignSystem/Example/Sources/ContentView.swift +++ b/Projects/Shared/DesignSystem/Example/Sources/ContentView.swift @@ -55,7 +55,7 @@ struct ContentView: View { } NavigationLink { - + BottomSheetDetailView() } label: { Text("BottomSheet") } diff --git a/Projects/Shared/DesignSystem/Sources/Component/BottomSheet/BottomSheet.swift b/Projects/Shared/DesignSystem/Sources/Component/BottomSheet/BottomSheet.swift new file mode 100644 index 0000000..7ed52a5 --- /dev/null +++ b/Projects/Shared/DesignSystem/Sources/Component/BottomSheet/BottomSheet.swift @@ -0,0 +1,67 @@ +// +// BottomSheet.swift +// DesignSystemExample +// +// Created by devMinseok on 8/12/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +extension View { + public func bottomSheet< + Item: Identifiable, + Content: View + >( + item: Binding, + @ViewBuilder content: @escaping (Item) -> Content + ) -> some View { + ZStack(alignment: .bottom) { + self + .zIndex(1) + + if let wrappedItem = item.wrappedValue { + Global.Color.black.opacity(Global.Opacity._50d) + .ignoresSafeArea() + .onTapGesture { + item.wrappedValue = nil + } + .transition( + .opacity.animation(.easeInOut) + ) + .zIndex(2) + VStack(spacing: .zero) { + HStack(alignment: .center) { + RoundedRectangle(cornerRadius: 2) + .fill(Global.Color.gray400) + .frame(width: 50, height: 4) + } + .frame(height: 30) + .frame(maxWidth: .infinity) + .background(Global.Color.white) + .cornerRadius(24, corners: [.topLeft, .topRight]) + .gesture( + DragGesture(minimumDistance: 20) + .onEnded { value in + if value.translation.height > 100 { + withAnimation { + item.wrappedValue = nil + } + } + } + ) + + content(wrappedItem) + .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) + } + } + } +} diff --git a/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyle.swift b/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyle.swift new file mode 100644 index 0000000..cca4731 --- /dev/null +++ b/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyle.swift @@ -0,0 +1,45 @@ +// +// RoundButtonStyle.swift +// DesignSystem +// +// Created by devMinseok on 8/12/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +public struct RoundButtonStyle: ButtonStyle { + let level: RoundButtonStyleLevel + + public init(level: RoundButtonStyleLevel) { + self.level = level + } + + public func makeBody(configuration: Configuration) -> some View { + configuration.label + .frame(width: 88, height: 88) + .background( + getBackgroundColor(isPressed: configuration.isPressed), + in: RoundedRectangle(cornerRadius: 44) + ) + .foregroundColor(Global.Color.white) + .labelStyle(SingleIconButtonLabelStyle()) + .singleIconButtonDetailStyle(DefaultSingleIconButtonDetailStyle()) + } + + private func getBackgroundColor(isPressed: Bool) -> Color { + if isPressed { + return level.pressedBackground + } else { + return level.defaultBackground + } + } +} + +extension ButtonStyle where Self == RoundButtonStyle { + public static func round( + level: RoundButtonStyleLevel + ) -> Self { + return RoundButtonStyle(level: level) + } +} diff --git a/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyleLevel.swift b/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyleLevel.swift new file mode 100644 index 0000000..df0c6f6 --- /dev/null +++ b/Projects/Shared/DesignSystem/Sources/Component/Button/Round/RoundButtonStyleLevel.swift @@ -0,0 +1,29 @@ +// +// RoundButtonStyleLevel.swift +// DesignSystem +// +// Created by devMinseok on 8/12/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +public enum RoundButtonStyleLevel { + case primary + case secondary +} + +extension RoundButtonStyleLevel { + var defaultBackground: Color { + switch self { + case .primary: + return Alias.Color.Background.accent1 + case .secondary: + return Alias.Color.Background.inverse + } + } + + var pressedBackground: Color { + return defaultBackground.opacity(0.9) + } +} diff --git a/Projects/Shared/DesignSystem/Sources/Helper/View+Extension.swift b/Projects/Shared/DesignSystem/Sources/Helper/View+Extension.swift new file mode 100644 index 0000000..61aa651 --- /dev/null +++ b/Projects/Shared/DesignSystem/Sources/Helper/View+Extension.swift @@ -0,0 +1,29 @@ +// +// View+Extension.swift +// DesignSystem +// +// Created by devMinseok on 8/12/24. +// Copyright © 2024 PomoNyang. All rights reserved. +// + +import SwiftUI + +extension View { + func cornerRadius(_ radius: CGFloat, corners: UIRectCorner) -> some View { + clipShape(RoundedCorner(radius: radius, corners: corners)) + } +} + +private 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) + } +}