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:
privateenumContentTab:Hashable{case home
case music
case user
}import SwiftUI
structContentView:View{@StateprivatevarselectedTab:ContentTab=.home
varbody:someView{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.