Understanding SwiftUI's TabView
I'm a beginner iOS developer—I don't work with iOS and Swift day to day, but I'm curious about what the platform offers. Apple's documentation for the iOS 26 Tab API is text-heavy with few visuals. I wanted to understand how the new TabView actually behaves, so I built several examples and recorded them.
This post covers:
- The redesigned Tab API syntax
- Liquid glass effects
- Special tab roles (search)
- Badge notifications
- What you cannot customize
- Practical workarounds
API Redesign
iOS 26 replaced .tabItem
modifiers with a dedicated Tab
component. The old API required wrapping labels in closures. The new syntax consolidates everything:
Before:
Text("Home").tabItem { Label("Home", systemImage: "house") }
After:
Tab("Home", systemImage: "house") { Text("Home") }
Less nesting, clearer intent.
Example Setup
For visual consistency across examples, I extracted styling into TabViewHelpers.swift
:
// TabViewHelpers.swift - shared across all examples
extension View {
var rainbowGradient: some View {
LinearGradient(
colors: [.red, .orange, .yellow, .green, .blue, .purple],
startPoint: .topLeading,
endPoint: .bottomTrailing
)
.ignoresSafeArea()
}
func tabContent(_ text: String) -> some View {
Text(text)
.font(.system(size: 40, weight: .bold))
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
.padding(.bottom, 100)
.background(rainbowGradient)
}
}
This keeps examples focused on TabView structure rather than presentation details. The rainbow gradient makes liquid glass effects more visible in videos.
Basic Tab Example
Here's a standard TabView with three tabs:
TabView {
Tab("Home", systemImage: "house") {
tabContent("Home")
}
Tab("Automation", systemImage: "checkmark.circle") {
tabContent("Automation")
}
Tab("Discover", systemImage: "star") {
tabContent("Discover")
}
}
Each Tab
needs a label, icon, and content. TabView handles state persistence, animations, and accessibility automatically.
iOS 26 introduced "liquid glass"—a frosted tab bar that adapts to content behind it. The effect is automatic. As you switch tabs, the backdrop blur adjusts dynamically. No configuration needed.
The video shows the basic TabView. Notice how the gradient shifts through the frosted tab bar as you navigate:
Search Role
Tab(role: .search)
is special. Unlike regular tabs where you specify everything, the search role automatically provides the magnifying glass icon and semantic context to iOS:
TabView {
Tab("Issues", systemImage: "newspaper") {
tabContent("Issues")
}
Tab("About", systemImage: "info.circle") {
tabContent("About")
}
Tab(role: .search) {
tabContent("Search")
}
}
The magnifying glass is locked in—no customization. This ensures consistent search recognition across iOS. Apps like App Store and Music follow this pattern.
The video shows the search tab with its system-provided icon:
Badges
.badge()
adds notification bubbles to tabs. To demonstrate this, I added buttons that update state:
struct BadgedTabView: View {
@State private var messageCount = 3
@State private var notificationCount = 7
var body: some View {
VStack {
// Control buttons
HStack {
Button("Add Message") {
messageCount += 1
}
Button("Clear Notifications") {
notificationCount = 0
}
}
.padding()
TabView {
Tab("Messages", systemImage: "message") {
tabContent("Messages (\(messageCount))")
}
.badge(messageCount)
Tab("Notifications", systemImage: "bell") {
tabContent("Notifications (\(notificationCount))")
}
.badge(notificationCount)
Tab("Profile", systemImage: "person") {
tabContent("Profile")
}
}
}
}
}
Badges hide automatically at 0. iOS handles positioning and styling. Messages, Mail, and Phone use this for unread counts.
The video shows the buttons in action:
Limitations
TabView's declarative approach comes with restrictions. Apple enforces conventions to maintain iOS consistency.
Search Is Locked Down
Tab(role: .search)
cannot be repurposed:
- Cannot replace with "Add" button or other actions
- Icon is fixed—no customization
- Only one search role per TabView
- iOS determines position
Apple's reasoning: search should be instantly recognizable. The magnifying glass is universal. Breaking this would confuse users across apps.
Other Restrictions
More than 5 tabs: iOS adds a "More" tab automatically. Cannot customize or remove it. System decides which tabs get hidden.
iPad layout: iOS 26 forces tab bars near the top. Cannot use old bottom position. Sidebar toggle is system-controlled.
Tab bar appearance: Limited color, blur, spacing customization. Liquid glass is default—cannot disable or use custom materials.
Tab ordering: Users can reorder in "More" menu (requires customizationID
). Sidebar doesn't always sync with TabView order.
Apple's restrictions enforce their design language. Most apps stay within TabView's constraints—the defaults cover common cases and maintain iOS consistency.
Design Guidelines
Apple's recommendations:
Structure
- 3-5 tabs on iPhone (optimal usability)
- Clear SF Symbol icons
- Concise titles (1-2 words)
- Sparse badging (important notifications only)
Hierarchy
- Primary actions in main tabs
- Secondary content in TabSections (iOS 26+)
- Search always uses
Tab(role: .search)
Responsive
- Size class adaptation for different screens
.sidebarAdaptable
for iPad- 44pt minimum touch targets
Following these maintains iOS consistency and improves usability.