Skip to content

Commit 22d55d4

Browse files
committed
feat(Button): allow usage of children inside Buttons
1 parent 224250c commit 22d55d4

File tree

4 files changed

+51
-16
lines changed

4 files changed

+51
-16
lines changed

ios/SwiftUINode.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ private struct NodeWrapper: Decodable {
7575
case "Section":
7676
node = try GenericNode<SectionProps>(from: decoder)
7777
case "Group":
78-
node = try GenericNode<EmptyProps>(from: decoder) // No props for Group
78+
node = try GenericNode<GroupProps>(from: decoder)
7979
case "HStack":
8080
node = try GenericNode<HStackProps>(from: decoder)
8181
case "VStack":

ios/SwiftUIRootView.swift

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,14 @@ public class SwiftUIRootView: SwiftUIContainerView {
3535

3636
private func buildSwiftUIView(from node: any SwiftUINode) -> AnyView {
3737
switch node {
38-
case let group as GenericNode<EmptyProps>:
39-
AnyView(Group {
38+
case let group as GenericNode<GroupProps>:
39+
AnyView(GroupView(props: group.props, content: {
4040
if let children = group.children {
4141
ForEach(children, id: \.id) { child in
4242
self.buildSwiftUIView(from: child)
4343
}
4444
}
45-
})
45+
}))
4646
case let hstack as GenericNode<HStackProps>:
4747
AnyView(HStackView(props: hstack.props, content: {
4848
if let children = hstack.children {
@@ -99,6 +99,14 @@ public class SwiftUIRootView: SwiftUIContainerView {
9999
}
100100
}
101101
}))
102+
case let button as GenericNode<ButtonProps>:
103+
AnyView(ButtonView(props: button.props, content: {
104+
if let children = button.children {
105+
ForEach(children, id: \.id) { child in
106+
self.buildSwiftUIView(from: child)
107+
}
108+
}
109+
}))
102110
case let text as GenericNode<TextProps>:
103111
AnyView(TextView(props: text.props))
104112
case let textField as GenericNode<TextFieldProps>:
@@ -109,8 +117,6 @@ public class SwiftUIRootView: SwiftUIContainerView {
109117
AnyView(DatePickerView(props: datePicker.props))
110118
case let stepper as GenericNode<StepperProps>:
111119
AnyView(StepperView(props: stepper.props))
112-
case let button as GenericNode<ButtonProps>:
113-
AnyView(ButtonView(props: button.props))
114120
case let toggle as GenericNode<ToggleProps>:
115121
AnyView(ToggleView(props: toggle.props))
116122
case let slider as GenericNode<SliderProps>:
@@ -176,9 +182,9 @@ public class SwiftUIRootView: SwiftUIContainerView {
176182
let updatedProps = try decoder.decode(SectionProps.self, from: updatedPropsData)
177183
section.props.merge(from: updatedProps)
178184

179-
case let group as GenericNode<EmptyProps>:
180-
// GroupNode has no props to merge
181-
print("GroupNode has no props to update for id \(identifier)")
185+
case let group as GenericNode<GroupProps>:
186+
let updatedProps = try decoder.decode(GroupProps.self, from: updatedPropsData)
187+
group.props.merge(from: updatedProps)
182188

183189
case let hstack as GenericNode<HStackProps>:
184190
let updatedProps = try decoder.decode(HStackProps.self, from: updatedPropsData)

ios/components/Button/ButtonProps.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import SwiftUI
22

33
public final class ButtonProps: ObservableObject, Decodable {
4-
@Published var title: String = "Button"
4+
@Published var title: String? = nil
55
@Published var buttonStyle: ButtonStyle = .default
66
@Published var disabled: Bool = false
77
@Published public var style: StyleProps?
@@ -15,6 +15,7 @@ public final class ButtonProps: ObservableObject, Decodable {
1515
case borderedProminent
1616
case borderless
1717
// Custom
18+
case scale
1819
case subtle
1920
case picker
2021

@@ -34,6 +35,8 @@ public final class ButtonProps: ObservableObject, Decodable {
3435
// Custom
3536
case .subtle:
3637
view.buttonStyle(SubtleOpacityButtonStyle())
38+
case .scale:
39+
view.buttonStyle(ScaleButtonStyle())
3740
case .picker:
3841
view.buttonStyle(PickerButtonStyle())
3942
}
@@ -46,7 +49,7 @@ public final class ButtonProps: ObservableObject, Decodable {
4649

4750
public required init(from decoder: Decoder) throws {
4851
let container = try decoder.container(keyedBy: CodingKeys.self)
49-
title = try container.decodeIfPresent(String.self, forKey: .title) ?? ""
52+
title = try container.decodeIfPresent(String.self, forKey: .title)
5053
if let buttonStyleString = try container.decodeIfPresent(String.self, forKey: .buttonStyle), let style = ButtonStyle(rawValue: buttonStyleString) {
5154
buttonStyle = style
5255
} else {
@@ -83,3 +86,14 @@ struct SubtleOpacityButtonStyle: ButtonStyle {
8386
.animation(configuration.isPressed ? .linear(duration: 0.05) : .easeInOut(duration: 0.25), value: configuration.isPressed)
8487
}
8588
}
89+
90+
struct ScaleButtonStyle: ButtonStyle {
91+
var normalScale: Double = 1.0
92+
var pressedScale: Double = 0.95
93+
94+
func makeBody(configuration: Configuration) -> some View {
95+
configuration.label
96+
.scaleEffect(configuration.isPressed ? pressedScale : normalScale)
97+
.animation(.spring(response: 0.3, dampingFraction: 0.6), value: configuration.isPressed)
98+
}
99+
}
Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,30 @@
11
import SwiftUI
22

3-
public struct ButtonView: View {
3+
public struct ButtonView<Content: View>: View {
44
@ObservedObject public var props: ButtonProps
5+
let content: () -> Content
6+
7+
public init(props: ButtonProps, @ViewBuilder content: @escaping () -> Content) {
8+
self.props = props
9+
self.content = content
10+
}
511

612
public var body: some View {
7-
props.buttonStyle.applyStyle(
8-
Button(props.title) {
9-
props.onPress?()
13+
if props.title != nil {
14+
return AnyView(props.buttonStyle.applyStyle(
15+
Button(props.title!, role: nil, action: props.onPress ?? {})
16+
.disabled(props.disabled)
17+
.applyStyles(props.style)
18+
.contentShape(Rectangle())
19+
))
20+
}
21+
return AnyView(props.buttonStyle.applyStyle(
22+
Button(role: nil, action: props.onPress ?? {}) {
23+
content()
1024
}
1125
.disabled(props.disabled)
1226
.applyStyles(props.style)
13-
)
27+
.contentShape(Rectangle())
28+
))
1429
}
1530
}

0 commit comments

Comments
 (0)