A reusable SwiftUI tab container with:
- Generic selection type (
Selection: Hashable) so your tab enum lives outside the component. - Builder-style tab declarations via
CustomTabItem. - Optional per-tab tooltips using the custom
.tooltip(...)modifier. - Drag-to-switch and tap-to-switch tab behavior.
CustomTabView/Reusable Views/CustomTabView.swiftCustomTabView/Reusable Views/TooltipButton.swift
Define your tab enum in your feature/screen file, not inside CustomTabView.swift:
private enum ContentTab: Hashable {
case home
case music
case user
}import SwiftUI
struct ContentView: View {
@State private var selectedTab: ContentTab = .home
var body: some View {
ZStack {
CustomTabView(selectedTab: $selectedTab) {
CustomTabItem("Home", systemImage: "house.fill", value: .home) {
Text("Home")
}
CustomTabItem("Music", systemImage: "music.note", value: .music) {
Text("Music")
}
CustomTabItem("User", systemImage: "person.fill", value: .user) {
Text("User")
}
}
}
.tooltipHost() // required when any tooltip is used
}
}You can attach tooltip directly to CustomTabItem:
CustomTabItem("User", systemImage: "person.fill", value: .user) {
Text("User")
}
.tooltip(position: .top, closeButton: .hidden, tooltipWidth: 220) {
Text("User tab")
.font(.caption.weight(.semibold))
}CustomTabItem("User", systemImage: "person.fill", value: .user) {
Text("User")
}
.tooltip("User tab", position: .top)Available parameters on CustomTabItem.tooltip(...):
isPresented: Binding<Bool>?(optional external control)position: TooltipPosition(.top,.bottom,.leading,.trailing)closeButton: TooltipCloseButton(.visible,.hidden)tooltipWidth,distanceFromAnchor,edgePadding,arrowSize,cornerRadiustapToToggle,bubbleBackground,shadowColor,animationDuration
If isPresented is not provided, tooltip visibility is internally managed and toggles on tap.
- Keep
.tooltipHost()on an ancestor container (commonly the rootZStack) whenever tooltips are used. CustomTabViewremains generic and does not require any app-specific enum in the reusable file.- Tooltips are configured per tab item, so each tab can have different tooltip behavior.