Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add onclick support to Button. #157

Merged
merged 1 commit into from
Aug 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 29 additions & 8 deletions Sources/Slipstream/W3C/Elements/Forms/Button.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,46 @@ import SwiftSoup
///
/// - SeeAlso: W3C [button](https://html.spec.whatwg.org/multipage/form-elements.html#the-button-element) specification.
@available(iOS 17.0, macOS 14.0, *)
public struct Button<Content>: View where Content: View {
public struct Button<Label>: View where Label: View {
/// Creates a button that displays a custom label and executes a custom action
/// when clicked.
public init(action: String, @ViewBuilder label: @escaping () -> Label) {
self.label = label
self.action = action
}

/// Creates a button that displays a custom label.
public init(@ViewBuilder content: @escaping () -> Content) {
self.content = content
public init(@ViewBuilder label: @escaping () -> Label) {
self.label = label
self.action = nil
}

/// Creates a button that generates its label from a string.
public init(_ text: String) where Content == DOMString {
self.content = {
public init(_ text: String) where Label == DOMString {
self.label = {
DOMString(text)
}
self.action = nil
}

@_documentation(visibility: private)
@ViewBuilder public let content: () -> Content
/// Creates a button that generates its label from a string and executes a custom
/// action when clicked.
public init(_ text: String, action: String) where Label == DOMString {
self.label = {
DOMString(text)
}
self.action = action
}

@ViewBuilder private let label: () -> Label
private let action: String?

@_documentation(visibility: private)
public func render(_ container: Element, environment: EnvironmentValues) throws {
let element = try container.appendElement("button")
try self.content().render(element, environment: environment)
if let action {
try element.attr("onclick", action)
}
try self.label().render(element, environment: environment)
}
}
9 changes: 9 additions & 0 deletions Tests/SlipstreamTests/W3C/Forms/ButtonTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,19 @@ struct ButtonTests {
@Test func emptyBlock() throws {
try #expect(renderHTML(Button {}) == "<button></button>")
}

@Test func withText() throws {
try #expect(renderHTML(Button("Tap me")) == #"<button>Tap me</button>"#)
}

@Test func withAction() throws {
try #expect(renderHTML(Button(action: "alert('hello world')") {
DOMString("Tap me")
}) == #"<button onclick="alert('hello world')">Tap me</button>"#)

try #expect(renderHTML(Button("Tap me", action: "alert('hello world')")) == #"<button onclick="alert('hello world')">Tap me</button>"#)
}

@Test func withCustomContent() throws {
try #expect(renderHTML(Button {
Text("Tap me")
Expand Down