More control of TipKit arrow locations

Hello! Based on the lack of forum posts, I think I'm one of the first people to really be diving into TipKit. :) I'm trying to use a tip to coax users toward a button in the toolbar of a NavigationView. The docs say to put the TipView "close to the content", but the best I can do for the NavigationView toolbar is to put it in one of the views inside the Navigation View itself. I'm using a TipView with an arrowEdge: .top parameter, which results in this:

I'd love to be able to move the arrow tip under the plus button. Is that possible in this early beta stage? Do I need to restructure my view hierarchy somehow?

Answered by in 762249022

The reason the tip isn't working with the toolbar button is a known issue in TipKit. It only affects buttons that are placed in SwiftUI toolbars. Until that gets fixed, here’s a workaround you can use: apply a style to the button. It can be any style. Some examples are bordered, borderless, plain and borderedProminent. Here's a fixed version of your code that uses this workaround:

ToolbarItem(placement: .topBarLeading) {
						Button(action: {isSetting = true}) {
							Label("Edit", systemImage: "gear").labelStyle(.iconOnly)
						}
           .buttonStyle(.plain) // This line fixes the issue!
           .popoverTip(editTip)
}

Give this a shot and let us know if it works.

Yes -- use the .popoverTip modifier on the "+" button in your ToolBarItem directly.

.popoverTip takes a tip: parameter that will be the Tip struct you've already defined. It also takes an arrowEdge.

That seems to work for buttons in other views, but the .popoverTip modifier on a button inside a ToolbarItem. Here's a snippet:

			}.navigationBarTitle("App Name").navigationBarTitleDisplayMode(.inline)
				.toolbar {
					ToolbarItem(placement: .topBarLeading) {
						Button(action: {isSetting = true}) {
							Label("Edit", systemImage: "gear").labelStyle(.iconOnly)
						}.popoverTip(editTip) // this doesn't work here
					}

It looks like the problem was your "Label" in the button.

If you just use an Image as your button content, the tip will work:

import SwiftUI
import TipKit

struct ContentView: View {
    @State var isSetting = false
    var body: some View {
        NavigationStack {
            
            VStack {
                Image(systemName: "globe")
                    .imageScale(.large)
                    .foregroundStyle(.tint)
                Text("Hello, world!")
                Text("isSetting: \(isSetting.description)")
            }
            .padding()
            .navigationTitle("Hello World")
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button(action: { isSetting = true} ){
                        Image(systemName: "gear")
                    }
                    .popoverTip(TestTip())
                }
            }
        }
    }
}
                

struct TestTip: Tip {
    var title: Text {
        Text("This is only a test")
    }
}

#Preview {
    ContentView()
}

The reason the tip isn't working with the toolbar button is a known issue in TipKit. It only affects buttons that are placed in SwiftUI toolbars. Until that gets fixed, here’s a workaround you can use: apply a style to the button. It can be any style. Some examples are bordered, borderless, plain and borderedProminent. Here's a fixed version of your code that uses this workaround:

ToolbarItem(placement: .topBarLeading) {
						Button(action: {isSetting = true}) {
							Label("Edit", systemImage: "gear").labelStyle(.iconOnly)
						}
           .buttonStyle(.plain) // This line fixes the issue!
           .popoverTip(editTip)
}

Give this a shot and let us know if it works.

I wonder why there isn't an option to TipView(... arrowAlignment: .topTrailing) instead of only arrowEdge? It's difficult to back port the .popoverTip as it required a tip: Tip parameter which is iOS17+ only.. so the way to go is via TipView.. but it lacks more custom alignments of the arrow.

+1

More control of TipKit arrow locations
 
 
Q