I am building a sample music project exclusively for visionOS, for those who got my book, Exploring MusicKit and Apple Music API. This post covers working with TabView with SwiftUI in visionOS and how to make the most of it.

Working with TabView in SwiftUI

Like other platforms, you can use a TabView and pass a Hashable selection value to keep track of the current tab.

import SwiftUI

struct ContentView: View {
  @State private var selectedTab: TabItem = .listenNow

  var body: some View {
    TabView(selection: $selectedTab) {
      ForEach(TabItem.allCases, id: \.self) { tab in
          .tabItem {
            Label(tab.name, systemImage: tab.image)

#Preview {

enum TabItem: CaseIterable {
  case listenNow
  case browse
  case musicVideos
  case radio
  case library
  case search

  var name: String {
    switch self {
      case .listenNow: return "Listen Now"
      case .browse: return "Browse"
      case .musicVideos: return "Music Videos"
      case .radio: return "Radio"
      case .library: return "Library"
      case .search: return "Search"

  var image: String {
    switch self {
      case .listenNow: return "play.circle"
      case .browse: return "square.grid.2x2"
      case .musicVideos: return "music.note.tv"
      case .radio: return "dot.radiowaves.left.and.right"
      case .library: return "music.note.list"
      case .search: return "magnifyingglass"

While the code looks similar, the design of a TabView for visionOS is completely different from iOS. The vertical tab view hangs off or floats on the left side of the app, compared to the bottom on iOS. This view is what Apple calls as Ornaments. From the Human Interface Guidelines:

In visionOS, an ornament presents controls and information related to a window, without crowding or obscuring the window’s contents.

According to Apple designers, the idea is that it should not block the app's main content while still being quick to access when you need it.

Looking at the tab item for a little longer automatically expands to show the label for each item. For this reason, you should provide a symbol and a short text title for each tab.

If you look away, it automatically closes again to float and show icons only.

TabView and Accessibility Text Size

Increasing the font size to the largest accessibility text size does not affect the icon size, but the text label font size increases considerably.


As I continue exploring the world of visionOS, I enjoy the design elements it offers. The concept of "ornaments" is a prime example, providing a fresh approach to presenting controls and information within an app.

Use RevenueCat Paywalls to add paywalls in one line of code.

Implement subscription models with ease and handle the complexities of in-app purchases with RevenueCat's Paywalls.

Tagged in: