diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift index d798e3b2..33a4ebf2 100644 --- a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/CardPreview.swift @@ -8,9 +8,12 @@ struct CardPreview: View { var body: some View { VStack { PreviewWrapper(title: "UIKit") { - UKCard(model: self.model, content: cardContent) + UKCard(model: self.model, content: self.ukCardContent) .preview } + PreviewWrapper(title: "SwiftUI") { + SUCard(model: self.model, content: self.suCardContent) + } Form { Picker("Background Color", selection: self.$model.backgroundColor) { Text("Default").tag(Optional.none) @@ -38,30 +41,42 @@ struct CardPreview: View { } } } -} -#Preview { - CardPreview() -} + // MARK: - Helpers + + private func ukCardContent() -> UIView { + let titleLabel = UILabel() + titleLabel.text = "Card" + titleLabel.font = UniversalFont.mdHeadline.uiFont + titleLabel.textColor = UniversalColor.foreground.uiColor + titleLabel.numberOfLines = 0 -// MARK: - Helpers + let subtitleLabel = UILabel() + subtitleLabel.text = "Card is a container for text, images, and other content." + subtitleLabel.font = UniversalFont.mdBody.uiFont + subtitleLabel.textColor = UniversalColor.secondaryForeground.uiColor + subtitleLabel.numberOfLines = 0 -private func cardContent() -> UIView { - let titleLabel = UILabel() - titleLabel.text = "Card" - titleLabel.font = UniversalFont.mdHeadline.uiFont - titleLabel.textColor = UniversalColor.foreground.uiColor - titleLabel.numberOfLines = 0 + let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) + stackView.axis = .vertical + stackView.spacing = 8 - let subtitleLabel = UILabel() - subtitleLabel.text = "Card is a container for text, images, and other content." - subtitleLabel.font = UniversalFont.mdBody.uiFont - subtitleLabel.textColor = UniversalColor.secondaryForeground.uiColor - subtitleLabel.numberOfLines = 0 + return stackView + } - let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel]) - stackView.axis = .vertical - stackView.spacing = 8 + private func suCardContent() -> some View { + VStack(alignment: .leading, spacing: 8) { + Text("Card") + .foregroundStyle(UniversalColor.foreground.color) + .font(UniversalFont.mdHeadline.font) - return stackView + Text("Card is a container for text, images, and other content.") + .foregroundStyle(UniversalColor.secondaryForeground.color) + .font(UniversalFont.mdBody.font) + } + } +} + +#Preview { + CardPreview() } diff --git a/Sources/ComponentsKit/Components/Card/CardVM.swift b/Sources/ComponentsKit/Components/Card/Models/CardVM.swift similarity index 100% rename from Sources/ComponentsKit/Components/Card/CardVM.swift rename to Sources/ComponentsKit/Components/Card/Models/CardVM.swift diff --git a/Sources/ComponentsKit/Components/Card/SUCard.swift b/Sources/ComponentsKit/Components/Card/SUCard.swift new file mode 100644 index 00000000..bfea52e4 --- /dev/null +++ b/Sources/ComponentsKit/Components/Card/SUCard.swift @@ -0,0 +1,51 @@ +import SwiftUI + +/// A SwiftUI component that serves as a container for provided content. +/// +/// - Example: +/// ```swift +/// SUCard( +/// model: .init(), +/// content: { +/// Text("This is the content of the card.") +/// } +/// ) +/// ``` +public struct SUCard: View { + // MARK: - Properties + + /// A model that defines the appearance properties. + public let model: CardVM + + @ViewBuilder private let content: () -> Content + + // MARK: - Initialization + + /// Initializer. + /// + /// - Parameters: + /// - model: A model that defines the appearance properties. + /// - content: The content that is displayed in the card. + public init( + model: CardVM, + content: @escaping () -> Content + ) { + self.model = model + self.content = content + } + + // MARK: - Body + + public var body: some View { + self.content() + .padding(self.model.contentPaddings.edgeInsets) + .background(self.model.preferredBackgroundColor.color) + .background(UniversalColor.background.color) + .cornerRadius(self.model.cornerRadius.value) + .overlay( + RoundedRectangle(cornerRadius: self.model.cornerRadius.value) + .stroke(UniversalColor.divider.color, lineWidth: 1.0) + ) + .shadow(self.model.shadow) + } +} diff --git a/Sources/ComponentsKit/Components/Card/UKCard.swift b/Sources/ComponentsKit/Components/Card/UKCard.swift index d20d8148..7554db8d 100644 --- a/Sources/ComponentsKit/Components/Card/UKCard.swift +++ b/Sources/ComponentsKit/Components/Card/UKCard.swift @@ -7,13 +7,14 @@ import UIKit /// ```swift /// let banner = UKCard( /// model: .init(), -/// content: { _ in +/// content: { /// let label = UILabel() /// label.text = "This is the content of the card." /// label.numberOfLines = 0 /// return label /// } /// ) +/// ``` open class UKCard: UIView, UKComponent { // MARK: - Typealiases diff --git a/Sources/ComponentsKit/Helpers/Paddings.swift b/Sources/ComponentsKit/Helpers/Paddings.swift index cc72392b..f6674901 100644 --- a/Sources/ComponentsKit/Helpers/Paddings.swift +++ b/Sources/ComponentsKit/Helpers/Paddings.swift @@ -1,4 +1,4 @@ -import Foundation +import SwiftUI /// Defines padding values for each edge. public struct Paddings: Hashable { @@ -50,3 +50,16 @@ public struct Paddings: Hashable { self.trailing = padding } } + +// MARK: - SwiftUI Helpers + +extension Paddings { + var edgeInsets: EdgeInsets { + return EdgeInsets( + top: self.top, + leading: self.leading, + bottom: self.bottom, + trailing: self.trailing + ) + } +} diff --git a/Sources/ComponentsKit/Modal/SwiftUI/ModalContent.swift b/Sources/ComponentsKit/Modal/SwiftUI/ModalContent.swift index 8e95c809..7e38352f 100644 --- a/Sources/ComponentsKit/Modal/SwiftUI/ModalContent.swift +++ b/Sources/ComponentsKit/Modal/SwiftUI/ModalContent.swift @@ -63,10 +63,7 @@ struct ModalContent: View { .clipShape(RoundedRectangle( cornerRadius: self.model.cornerRadius.value )) - .padding(.top, self.model.outerPaddings.top) - .padding(.leading, self.model.outerPaddings.leading) - .padding(.bottom, self.model.outerPaddings.bottom) - .padding(.trailing, self.model.outerPaddings.trailing) + .padding(self.model.outerPaddings.edgeInsets) } private var bodyTopPadding: CGFloat { diff --git a/Sources/ComponentsKit/Shared/Types/Shadow.swift b/Sources/ComponentsKit/Shared/Types/Shadow.swift index 904d15d0..2be6dd37 100644 --- a/Sources/ComponentsKit/Shared/Types/Shadow.swift +++ b/Sources/ComponentsKit/Shared/Types/Shadow.swift @@ -1,3 +1,4 @@ +import SwiftUI import UIKit /// Defines shadow options for components. @@ -61,3 +62,16 @@ extension UIView { self.layer.shadowOpacity = 1 } } + +// MARK: - SwiftUI + Shadow + +extension View { + func shadow(_ shadow: Shadow) -> some View { + self.shadow( + color: shadow.color.color, + radius: shadow.radius, + x: shadow.offset.width, + y: shadow.offset.height + ) + } +}