swiftswiftuivisionos

I want to create a side window for the main window in VisionOS


This is what I want to achieve

I want to create a window that's main and on the right side, I want to have another window but this should not have the controls to close as the main window has in the bottom. Is this possible? If the user drags the main window, the side window should follow it maintaining it's position as to the right of the main window.

I tried to create separate views for main and side windows. Tried doing this but the side window didn't appear.

import SwiftUI

@main
struct App: App {
    var appState = AppState()
    
    var body: some Scene {
        WindowGroup {
            let feedViewModel = FeedViewModel(appState: appState)
        
            ContentView(feedViewModel: feedViewModel)
                .environmentObject(appState)
        } // Main Window
    
        WindowGroup {
            VideoListView()
        } // Side Window
    }
}

Solution

  • The type of layout you're describing can be achieved using the .ornament modifier combined with .rotation3DEffect to rotate the panels to face the user.

    enter image description here

    struct ContentView: View {
        private let ornamentSize: CGSize = .init(width: 400, height: 720)
        private let ornamentSpacing: CGFloat = 80
        private var spacerWidth: CGFloat {
            ornamentSize.width + ornamentSpacing
        }
    
        var body: some View {
            NavigationSplitView {
                List {
                    ForEach(0..<20) { i in
                        Text("\(i)")
                    }
                }
                .navigationTitle("Example")
            } detail: {
                grid
            }
            .ornament(attachmentAnchor: .scene(.leading)) {
                leadingWindowView
            }
            .ornament(attachmentAnchor: .scene(.trailing)) {
                trailingWindowView
            }
        }
        
        private var leadingWindowView: some View {
            HStack {
                Rectangle()
                    .foregroundColor(.clear)
                    .glassBackgroundEffect()
                    .frame(
                        width: ornamentSize.width,
                        height: ornamentSize.height
                    )
                    .overlay {
                        grid
                    }
                Spacer(minLength: spacerWidth)
            }
            .rotation3DEffect(.degrees(30), axis: .y)
        }
        
        private var trailingWindowView: some View {
            HStack {
                Spacer(minLength: spacerWidth)
                Rectangle()
                    .foregroundColor(.clear)
                    .glassBackgroundEffect()
                    .frame(
                        width: ornamentSize.width,
                        height: ornamentSize.height
                    )
                    .overlay {
                        grid
                    }
            }
            .rotation3DEffect(.degrees(-30), axis: .y)
        }
        
        private var grid: some View {
            ScrollView {
                LazyVGrid(
                    columns: [GridItem(.adaptive(minimum: 240), spacing: 24)],
                    spacing: 24) {
                    ForEach(0 ..< 12) { item in
                        RoundedRectangle(cornerRadius: 24)
                            .fill(Color.green)
                            .frame(height: 200)
                    }
                }
                .padding(24)
            }
        }
    }