Skip to content

Commit 9dfaf81

Browse files
authored
Merge pull request #24 from componentskit/Divider-SwiftUI
Divider SwiftUI
2 parents 1290188 + 871bad7 commit 9dfaf81

File tree

6 files changed

+196
-0
lines changed

6 files changed

+196
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import ComponentsKit
2+
import SwiftUI
3+
import UIKit
4+
5+
struct DividerPreview: View {
6+
@State private var model = DividerVM()
7+
8+
var body: some View {
9+
VStack {
10+
PreviewWrapper(title: "UIKit") {
11+
UKComponentPreview(model: self.model) {
12+
UKDivider(model: self.model)
13+
}
14+
}
15+
PreviewWrapper(title: "SwiftUI") {
16+
SUDivider(model: self.model)
17+
}
18+
Form {
19+
Picker("Orientation", selection: self.$model.orientation) {
20+
Text("Horizontal").tag(DividerVM.DividerOrientation.horizontal)
21+
Text("Vertical").tag(DividerVM.DividerOrientation.vertical)
22+
}
23+
SizePicker(selection: self.$model.size)
24+
Picker("Color", selection: self.$model.color) {
25+
Text("Default").tag(Palette.Base.divider)
26+
Text("Primary").tag(UniversalColor.primary)
27+
Text("Secondary").tag(UniversalColor.secondary)
28+
Text("Accent").tag(UniversalColor.accent)
29+
Text("Success").tag(UniversalColor.success)
30+
Text("Warning").tag(UniversalColor.warning)
31+
Text("Danger").tag(UniversalColor.danger)
32+
Text("Custom").tag(UniversalColor.universal(.uiColor(.systemPurple)))
33+
}
34+
}
35+
}
36+
}
37+
}
38+
39+
#Preview {
40+
DividerPreview()
41+
}

Examples/DemosApp/DemosApp/Core/App.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ struct App: View {
1212
NavigationLinkWithTitle("Checkbox") {
1313
CheckboxPreview()
1414
}
15+
NavigationLinkWithTitle("Divider") {
16+
DividerPreview()
17+
}
1518
NavigationLinkWithTitle("Input Field") {
1619
InputFieldPreview()
1720
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import Foundation
2+
3+
extension DividerVM {
4+
/// Defines the possible orientations for the divider.
5+
public enum DividerOrientation {
6+
case horizontal
7+
case vertical
8+
}
9+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import Foundation
2+
3+
/// A model that defines the appearance properties for a divider component.
4+
public struct DividerVM: ComponentVM {
5+
/// The orientation of the divider (horizontal or vertical).
6+
///
7+
/// Defaults to `.horizontal`.
8+
public var orientation: DividerOrientation = .horizontal
9+
10+
/// The color of the divider.
11+
///
12+
/// Defaults to `Palette.Base.divider`.
13+
public var color: UniversalColor = Palette.Base.divider
14+
15+
/// The predefined size of the divider, which affects its thickness.
16+
///
17+
/// Defaults to `.medium`.
18+
public var size: ComponentSize = .medium
19+
20+
/// Initializes a new instance of `DividerVM` with default values.
21+
public init() {}
22+
}
23+
24+
// MARK: - Shared Helpers
25+
26+
extension DividerVM {
27+
var lineSize: CGFloat {
28+
switch self.size {
29+
case .small:
30+
return 0.5
31+
case .medium:
32+
return 1.0
33+
case .large:
34+
return 2.0
35+
}
36+
}
37+
}
38+
39+
// MARK: - UIKit Helpers
40+
41+
extension DividerVM {
42+
func shouldUpdateLayout(_ oldModel: Self) -> Bool {
43+
return self.orientation != oldModel.orientation
44+
|| self.size != oldModel.size
45+
}
46+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import SwiftUI
2+
3+
/// A SwiftUI component that displays a separating line.
4+
public struct SUDivider: View {
5+
// MARK: - Properties
6+
7+
/// A model that defines the appearance properties.
8+
public var model: DividerVM
9+
10+
@Environment(\.colorScheme) private var colorScheme
11+
12+
// MARK: - Initialization
13+
14+
/// Initializer.
15+
/// - Parameters:
16+
/// - model: A model that defines the appearance properties.
17+
public init(model: DividerVM = .init()) {
18+
self.model = model
19+
}
20+
21+
// MARK: - Body
22+
23+
public var body: some View {
24+
Rectangle()
25+
.fill(self.model.color.color(for: self.colorScheme))
26+
.frame(
27+
maxWidth: self.model.orientation == .vertical ? self.model.lineSize : nil,
28+
maxHeight: self.model.orientation == .horizontal ? self.model.lineSize : nil
29+
)
30+
}
31+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import UIKit
2+
3+
/// A UIKit component that displays a separating line.
4+
open class UKDivider: UIView, UKComponent {
5+
// MARK: - Properties
6+
7+
/// A model that defines the appearance properties.
8+
public var model: DividerVM {
9+
didSet {
10+
self.update(oldValue)
11+
}
12+
}
13+
14+
// MARK: - UIView Properties
15+
16+
open override var intrinsicContentSize: CGSize {
17+
return self.sizeThatFits(UIView.layoutFittingExpandedSize)
18+
}
19+
20+
// MARK: - Initializers
21+
22+
/// Initializer.
23+
/// - Parameters:
24+
/// - model: A model that defines the appearance properties.
25+
public init(model: DividerVM = .init()) {
26+
self.model = model
27+
super.init(frame: .zero)
28+
self.style()
29+
}
30+
31+
public required init?(coder: NSCoder) {
32+
fatalError("init(coder:) has not been implemented")
33+
}
34+
35+
// MARK: - Setup
36+
37+
private func style() {
38+
self.backgroundColor = self.model.color.uiColor
39+
self.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
40+
self.setContentCompressionResistancePriority(.defaultLow, for: .vertical)
41+
}
42+
43+
// MARK: - Update
44+
45+
public func update(_ oldModel: DividerVM) {
46+
guard self.model != oldModel else { return }
47+
48+
self.backgroundColor = self.model.color.uiColor
49+
50+
if self.model.shouldUpdateLayout(oldModel) {
51+
self.invalidateIntrinsicContentSize()
52+
}
53+
}
54+
55+
// MARK: - UIView Methods
56+
57+
open override func sizeThatFits(_ size: CGSize) -> CGSize {
58+
let lineSize = self.model.lineSize
59+
switch self.model.orientation {
60+
case .vertical:
61+
return CGSize(width: lineSize, height: size.height)
62+
case .horizontal:
63+
return CGSize(width: size.width, height: lineSize)
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)