Allow DOMRenderer to render buttons with non-Text labels (#403) (#409)

Currently, `DOMRenderer` can only handle `Button`s where is the label is `Text`. If it is any other `View`, the `Button` is not rendered. This is the cause of #403.

This PR removes this restriction. Additionally, it expands the `ButtonStyle` demo to include `Button`s with complex labels.
This commit is contained in:
ezraberch 2021-06-07 12:17:43 -04:00 committed by GitHub
parent 44280847cf
commit da9843d07f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 46 additions and 23 deletions

View File

@ -18,9 +18,10 @@
import TokamakCore
import TokamakStaticHTML
extension _Button: ViewDeferredToRenderer where Label == Text {
extension _Button: ViewDeferredToRenderer {
@_spi(TokamakCore)
public var deferredBody: AnyView {
var attributes: [HTMLAttribute: String] = [:]
let listeners: [String: Listener] = [
"pointerdown": { _ in isPressed = true },
"pointerup": { _ in
@ -28,28 +29,21 @@ extension _Button: ViewDeferredToRenderer where Label == Text {
action()
},
]
if buttonStyle.type == DefaultButtonStyle.self {
return AnyView(DynamicHTML(
"button",
["class": "_tokamak-buttonstyle-default"],
listeners: listeners
) {
HTML("span", content: label.innerHTML(shouldSortAttributes: false) ?? "")
})
} else {
return AnyView(DynamicHTML(
"button",
["class": "_tokamak-buttonstyle-reset"],
listeners: listeners
) {
buttonStyle.makeBody(
configuration: _ButtonStyleConfigurationProxy(
label: AnyView(label),
isPressed: isPressed
).subject
)
.colorScheme(.light)
})
if buttonStyle.type != DefaultButtonStyle.self {
attributes["class"] = "_tokamak-buttonstyle-reset"
}
return AnyView(DynamicHTML(
"button",
attributes,
listeners: listeners
) {
buttonStyle.makeBody(
configuration: _ButtonStyleConfigurationProxy(
label: AnyView(label),
isPressed: isPressed
).subject
)
.colorScheme(.light)
})
}
}

View File

@ -30,12 +30,41 @@ public struct ButtonStyleDemo: View {
Button("Default Style") {
print("tapped")
}
Button(action: { print("tapped") }, label: {
HStack {
Text("Default").padding(.trailing, 5)
Circle().frame(width: 10, height: 10, alignment: .center)
Text("Style").padding(.horizontal, 5)
Ellipse().fill(Color.red).frame(width: 20, height: 10, alignment: .center)
Text("With").padding(.horizontal, 5)
Capsule().fill(Color.green).frame(width: 20, height: 10, alignment: .center)
Text("Complex").padding(.horizontal, 5)
Rectangle().fill(Color.blue).frame(width: 10, height: 10, alignment: .center)
Text("Label").padding(.leading, 5)
}
})
Button("Pressed Button Style") {
print("tapped")
}
.buttonStyle(
PressedButtonStyle(pressedColor: Color.red)
)
Button(action: { print("tapped") }, label: {
HStack {
Text("Pressed").padding(.trailing, 5)
Circle().frame(width: 10, height: 10, alignment: .center)
Text("Style").padding(.horizontal, 5)
Ellipse().fill(Color.red).frame(width: 20, height: 10, alignment: .center)
Text("With").padding(.horizontal, 5)
Capsule().fill(Color.green).frame(width: 20, height: 10, alignment: .center)
Text("Complex").padding(.horizontal, 5)
Rectangle().fill(Color.blue).frame(width: 10, height: 10, alignment: .center)
Text("Label").padding(.leading, 5)
}
})
.buttonStyle(
PressedButtonStyle(pressedColor: Color.red)
)
}
}
}