Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI macOS - Create clickable hyperlink

I would like to display a url that the user can click on in my macos app. What I have so far is this:

Text(url)
.onTapGesture {
    if let url = URL(string: self.url) {
        NSWorkspace.shared.open(url)
    }
}

However, this provides no visual indication to the user that the url is clickable. I want the text to be underlined and I want the cursor to change to a hand when the user hovers over it. How do I do that?

EDIT:

I found a custom extension for conditionally applying a modifier to a view from the swift forums:


extension View {

    func `if`<Content: View>(_ conditional: Bool, content: (Self) -> Content) -> some View {
        if conditional {
            return AnyView(content(self))
        } else {
            return AnyView(self)
        }
    }

}

after combining it with @Asperi's answer, I now have this:


@State private var isHoveringOverURL = false

Button(action: {
    if let url = URL(string: self.url) {
        NSWorkspace.shared.open(url)
    }

}) {
    Text(self.url)
        .font(.caption)
        .foregroundColor(Color.blue)
        .if(isHoveringOverURL) {
            $0.underline()
        }

}
.buttonStyle(PlainButtonStyle())
.onHover { inside in
    if inside {
        self.isHoveringOverURL = true
        NSCursor.pointingHand.push()
    } else {
        self.isHoveringOverURL = false
        NSCursor.pop()
    }
}

preview

like image 972
Peter Schorn Avatar asked Oct 28 '25 06:10

Peter Schorn


2 Answers

Here is possible solution. Tested with Xcode 11.4 / macOS 10.15.4

demo

Button(action: {
   // link action here
}) {
    Text("www.stackoverflow.com").underline()
        .foregroundColor(Color.blue)
}.buttonStyle(PlainButtonStyle())
.onHover { inside in
    if inside {
        NSCursor.pointingHand.push()
    } else {
        NSCursor.pop()
    }
}
like image 54
Asperi Avatar answered Oct 29 '25 20:10

Asperi


Do not use "Text" for this.

You need to use button:

Button("someLink") {
    FS.openTerminal(at: Urls.SshDir)
}
.buttonStyle(LinkButtonStyle())
like image 29
Andrew Avatar answered Oct 29 '25 20:10

Andrew



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!