diff --git a/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift new file mode 100644 index 00000000..c27eb21c --- /dev/null +++ b/Examples/DemosApp/DemosApp/ComponentsPreview/PreviewPages/BadgePreview.swift @@ -0,0 +1,38 @@ +import ComponentsKit +import SwiftUI +import UIKit + +struct BadgePreview: View { + @State private var model = BadgeVM { + $0.title = "Badge" + } + + var body: some View { + VStack { + PreviewWrapper(title: "SwiftUI") { + SUBadge(model: self.model) + } + Form { + Picker("Font", selection: self.$model.font) { + Text("Default").tag(Optional.none) + Text("Small").tag(UniversalFont.smButton) + Text("Medium").tag(UniversalFont.mdButton) + Text("Large").tag(UniversalFont.lgButton) + Text("Custom: system bold of size 16").tag(UniversalFont.system(size: 16, weight: .bold)) + } + ComponentOptionalColorPicker(selection: self.$model.color) + ComponentRadiusPicker(selection: self.$model.cornerRadius) { + Text("Custom: 4px").tag(ComponentRadius.custom(4)) + } + Picker("Style", selection: self.$model.style) { + Text("Filled").tag(BadgeVM.Style.filled) + Text("Light").tag(BadgeVM.Style.light) + } + } + } + } +} + +#Preview { + BadgePreview() +} diff --git a/Examples/DemosApp/DemosApp/Core/App.swift b/Examples/DemosApp/DemosApp/Core/App.swift index 380cd80a..ab7aaf9e 100644 --- a/Examples/DemosApp/DemosApp/Core/App.swift +++ b/Examples/DemosApp/DemosApp/Core/App.swift @@ -8,6 +8,9 @@ struct App: View { NavigationLinkWithTitle("Alert") { AlertPreview() } + NavigationLinkWithTitle("Badge") { + BadgePreview() + } NavigationLinkWithTitle("Button") { ButtonPreview() } diff --git a/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift b/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift new file mode 100644 index 00000000..5cc3cdb8 --- /dev/null +++ b/Sources/ComponentsKit/Components/Badge/Models/BadgeStyle.swift @@ -0,0 +1,9 @@ +import Foundation + +extension BadgeVM { + /// Defines the available visual styles for a badge. + public enum Style: Equatable { + case filled + case light + } +} diff --git a/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift b/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift new file mode 100644 index 00000000..a8c900e2 --- /dev/null +++ b/Sources/ComponentsKit/Components/Badge/Models/BadgeVM.swift @@ -0,0 +1,55 @@ +import SwiftUI + +/// A model that defines the appearance properties for a badge component. +public struct BadgeVM: ComponentVM { + /// The text displayed on the badge. + public var title: String = "" + + /// The color of the badge. + public var color: ComponentColor? + + /// The visual style of the badge. + /// + /// Defaults to `.filled`. + public var style: Style = .filled + + /// The font used for the badge's text. + /// + /// Defaults to `.smButton`. + public var font: UniversalFont = .smButton + + /// The corner radius of the badge. + /// + /// Defaults to `.medium`. + public var cornerRadius: ComponentRadius = .medium + + /// Paddings for the badge. + public var paddings: Paddings = .init(horizontal: 10, vertical: 8) + + /// Initializes a new instance of `BadgeVM` with default values. + public init() {} +} + +// MARK: Helpers + +extension BadgeVM { + /// Returns the background color of the badge based on its style. + var backgroundColor: UniversalColor { + switch self.style { + case .filled: + return self.color?.main ?? .content2 + case .light: + return self.color?.background ?? .content1 + } + } + + /// Returns the foreground color of the badge based on its style. + var foregroundColor: UniversalColor { + switch self.style { + case .filled: + return self.color?.contrast ?? .foreground + case .light: + return self.color?.main ?? .foreground + } + } +} diff --git a/Sources/ComponentsKit/Components/Badge/SUBadge.swift b/Sources/ComponentsKit/Components/Badge/SUBadge.swift new file mode 100644 index 00000000..216af4b5 --- /dev/null +++ b/Sources/ComponentsKit/Components/Badge/SUBadge.swift @@ -0,0 +1,30 @@ +import SwiftUI + +/// A SwiftUI component that displays a badge. +public struct SUBadge: View { + // MARK: Properties + + /// A model that defines the appearance properties. + public var model: BadgeVM + + // MARK: Initialization + + /// Initializes a new instance of `SUBadge`. + /// - Parameter model: A model that defines the appearance properties. + public init(model: BadgeVM) { + self.model = model + } + + // MARK: Body + + public var body: some View { + Text(self.model.title) + .font(self.model.font.font) + .padding(self.model.paddings.edgeInsets) + .foregroundStyle(self.model.foregroundColor.color) + .background(self.model.backgroundColor.color) + .clipShape( + RoundedRectangle(cornerRadius: self.model.cornerRadius.value()) + ) + } +}