Skip to content

Commit 03ee108

Browse files
committed
SUBadge
- SUBadge - BadgeVM - Badge Style - BadgePreview into App
1 parent 0590f98 commit 03ee108

File tree

6 files changed

+170
-0
lines changed

6 files changed

+170
-0
lines changed

Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/PreviewPickers.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,26 @@ struct ContainerRadiusPicker<Custom: View>: View {
123123

124124
// MARK: - FontPickers
125125

126+
struct BadgeFontPicker: View {
127+
let title: String
128+
@Binding var selection: UniversalFont?
129+
130+
init(title: String = "Font", selection: Binding<UniversalFont?>) {
131+
self.title = title
132+
self._selection = selection
133+
}
134+
135+
var body: some View {
136+
Picker(self.title, selection: self.$selection) {
137+
Text("Default").tag(Optional<UniversalFont>.none)
138+
Text("Small").tag(UniversalFont.smButton)
139+
Text("Medium").tag(UniversalFont.mdButton)
140+
Text("Large").tag(UniversalFont.lgButton)
141+
Text("Custom: system bold of size 16").tag(UniversalFont.system(size: 16, weight: .bold))
142+
}
143+
}
144+
}
145+
126146
struct BodyFontPicker: View {
127147
let title: String
128148
@Binding var selection: UniversalFont?
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import ComponentsKit
2+
import SwiftUI
3+
import UIKit
4+
5+
struct BadgePreview: View {
6+
@State private var model = BadgeVM {
7+
$0.title = "Badge"
8+
}
9+
10+
var body: some View {
11+
VStack {
12+
PreviewWrapper(title: "SwiftUI") {
13+
SUBadge(model: self.model)
14+
}
15+
Form {
16+
BadgeFontPicker(selection: self.$model.font)
17+
ComponentOptionalColorPicker(selection: self.$model.color)
18+
ComponentRadiusPicker(selection: self.$model.cornerRadius) {
19+
Text("Custom: 20px").tag(ComponentRadius.custom(20))
20+
}
21+
Picker("Style", selection: self.$model.style) {
22+
Text("Filled").tag(BadgeVM.Style.filled)
23+
Text("Light").tag(BadgeVM.Style.light)
24+
}
25+
}
26+
}
27+
}
28+
}
29+
30+
#Preview {
31+
BadgePreview()
32+
}

Examples/DemosApp/DemosApp/Core/App.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ struct App: View {
88
NavigationLinkWithTitle("Alert") {
99
AlertPreview()
1010
}
11+
NavigationLinkWithTitle("Badge") {
12+
BadgePreview()
13+
}
1114
NavigationLinkWithTitle("Button") {
1215
ButtonPreview()
1316
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Foundation
2+
3+
extension BadgeVM {
4+
/// Defines the available visual styles for a badge.
5+
public enum Style: Equatable {
6+
case filled
7+
case light
8+
}
9+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import SwiftUI
2+
3+
/// A model that defines the appearance properties for a badge component.
4+
public struct BadgeVM: ComponentVM {
5+
/// The text displayed on the badge.
6+
public var title: String = ""
7+
8+
/// The color of the badge.
9+
public var color: ComponentColor?
10+
11+
/// The visual style of the badge.
12+
///
13+
/// Can be either `.filled` or `.light`.
14+
/// Defaults to `.filled`.
15+
public var style: Style = .filled
16+
17+
/// The font used for the badge's text.
18+
///
19+
/// Defaults to `.smButton`.
20+
public var font: UniversalFont? = .smButton
21+
22+
/// The corner radius of the badge.
23+
///
24+
/// Defaults to `.medium`.
25+
public var cornerRadius: ComponentRadius = .medium
26+
27+
/// Vertical padding for the badge.
28+
///
29+
/// Defaults to `8`.
30+
public var verticalPadding: CGFloat = 8
31+
32+
/// Horizontal padding for the badge.
33+
///
34+
/// Defaults to `10`.
35+
public var horizontalPadding: CGFloat = 10
36+
37+
/// Initializes a new instance of `BadgeVM` with default values.
38+
public init() {}
39+
}
40+
41+
// MARK: Helpers
42+
43+
extension BadgeVM {
44+
/// Returns the background color of the badge based on its style.
45+
var backgroundColor: UniversalColor? {
46+
switch self.style {
47+
case .filled:
48+
let color = self.color?.main ?? .content2
49+
return color.enabled(true) // Badges are always "enabled"
50+
case .light:
51+
let color = self.color?.background ?? .content1
52+
return color.enabled(true)
53+
}
54+
}
55+
56+
/// Returns the foreground color of the badge based on its style.
57+
var foregroundColor: UniversalColor {
58+
switch self.style {
59+
case .filled:
60+
return (self.color?.contrast ?? .foreground).enabled(true)
61+
case .light:
62+
return (self.color?.main ?? .foreground).enabled(true)
63+
}
64+
}
65+
66+
/// Returns the preferred font for the badge text.
67+
var preferredFont: UniversalFont {
68+
if let font {
69+
return font
70+
}
71+
return .smButton
72+
}
73+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import SwiftUI
2+
3+
// MARK: - SUBadge
4+
5+
/// A SwiftUI component that displays a badge.
6+
public struct SUBadge: View {
7+
// MARK: Properties
8+
9+
/// A model that defines the appearance properties.
10+
public var model: BadgeVM
11+
12+
// MARK: Initialization
13+
14+
/// Initializes a new instance of `SUBadge`.
15+
/// - Parameter model: A model that defines the appearance properties.
16+
public init(model: BadgeVM) {
17+
self.model = model
18+
}
19+
20+
// MARK: Body
21+
22+
public var body: some View {
23+
Text(self.model.title)
24+
.font(self.model.preferredFont.font)
25+
.padding(.vertical, self.model.verticalPadding)
26+
.padding(.horizontal, self.model.horizontalPadding)
27+
.foregroundStyle(self.model.foregroundColor.color)
28+
.background(self.model.backgroundColor?.color ?? .clear)
29+
.clipShape(
30+
RoundedRectangle(cornerRadius: self.model.cornerRadius.value())
31+
)
32+
}
33+
}

0 commit comments

Comments
 (0)