Skip to content

Conversation

@davdroman
Copy link
Collaborator

@davdroman davdroman commented Jun 10, 2025

Bit late on this one, as I was working on #456 I realized we weren't running tests on macOS 15.

@davdroman davdroman merged commit 4cea34c into main Jun 10, 2025
@davdroman davdroman deleted the ci/macos-15 branch June 10, 2025 18:11
public static let v13 = Self(for: .v13)
public static let v14 = Self(for: .v14)
public static let v15 = Self(for: .v15)
@available(*, unavailable, message: "TabView is no longer backed by NSTabView starting macOS 15")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is true. I successfully patch TabView's underlying NSTabView on macOS 15.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for letting me know. I'll look into it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@thcyron hmm doesn't seem to work for me. Do you have a repro I could use? I'm running the latest macOS (15.6). The closest thing to a NSTabView the view graph inspector shows is a NSToolBarView but that's a private class of no real usefulness to anyone outside Apple.

Screenshot 2025-07-30 at 21 18 31

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@davdroman Wrap TabView in a GroupBox, then it's a NSTabView.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok that does work. The GroupBox thing is a significant caveat, so I think in order to avoid confusion I'll create a separate type for it altogether... something like .tabView(placement: .groupBox) and keep the unavailable message in .tabView to let users know about this.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To your knowledge, is there any other container view capable of this transformation other than GroupBox?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minimal example extracted from my app. Here, the ZStack seems to be key to force the TabView to not be part of the toolbar.

struct MainView: View {
    @ViewBuilder
    private var tabView: some View {
        TabView {
            Text("A")
            Text("B")
        }
        .introspect(.tabView, on: .macOS(.v15)) {
            $0.tabViewType = .noTabsNoBorder
        }
    }

    var body: some View {
        NavigationSplitView {
            Text("Sidebar")
        } detail: {
            ZStack {
                tabView
            }
        }
    }
}

Copy link
Collaborator Author

@davdroman davdroman Jul 31, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok thanks for this. I'm torn between being specific:

.tabView(placement: .groupBox)
.tabView(placement: .zStack)
// ... anything else?

or being general:

.tabView(placement: .nonRoot) // is there a better name? .container perhaps? or .detached?

As SwiftUI tends to add more and more views each year it might be a good shout to be a bit more general to cover all possible cases without having to do heavy maintenance...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the ZStack is crucial in the example I gave to get the traditional NSTabView layout, just wrapping in a ZStack isn't enough in all cases. If you drop the split view but keep the ZStack, you get the toolbar tab view layout again without a NSTabView.

var body: some View {
    ZStack {
        tabView
            .introspect(.tabView, on: .macOS(.v15)) {
                // never called
                $0.tabViewType = .noTabsNoBorder
            }
    }
}

As you said, we will never fully understand when a TabView is a NSTabView and when it isn't. Thus, I would suggest to keep the pre-1.4.0 behavior: allow .introspect(.tabView, on: .macOS(.v15)) and make it best-effort. If there is a NSTabView, you get it, but there isn't, you don't.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. PR is up now btw #477

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants