SwiftUI YouTube Home Screen


Goal:

Goal: Make Switch home screen.
Note: This is just a static page, no real functionality.

Thoughts:

I like the way it turned out. Outside of the Dalek and Peach photo, everything is a symbol. If I finish, i know I need to add the square backgrounds when a game isn't there and the highlight for whatever is currently being hovered over.

Image
Real YouTube homepage

Image
YouTube homepage made with SwiftUI

Code example

Here is the Swift code used to make this. Replace "peach" and "dalek" with your images. Also, notice the frame size in the main YouTubeView. I haven't learned proper scaling, so I just kept it at that scale.


import SwiftUI

struct YouTubeView: View {
    @State private var text = ""
    var body: some View {
        
        ZStack {
            RoundedRectangle(cornerRadius: 10, style: .continuous)
                .fill(Color.ytBackground)
                .opacity(0.5)
                .clipped()
                .clipShape(RoundedRectangle(cornerRadius: 18, style: .continuous))
            VStack{
                MenuBar()
                HStack{
                    SideBanner()
                    VStack{
                        FilterButtonBanner()
                        
                        HStack{
                            VideosView()
                            Spacer()
                        }
                        Spacer()
                    }
                   
                }
            }
        }
        .frame(width: 660, height: 450)
    }
}

struct VideosView: View {
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                HStack{
                    Thumbnail()
                    Thumbnail()
                    Thumbnail()
                }
                HStack{
                    Thumbnail()
                    Thumbnail()
                    Thumbnail()
                }
                HStack{
                    Thumbnail()
                    Thumbnail()
                    Thumbnail()
                }
                HStack{
                    Thumbnail()
                    Thumbnail()
                    Thumbnail()
                }
            }
            .padding(.horizontal)
        }
    }
}

struct Thumbnail: View {
    var verified: Bool = true
    var body: some View {
        Button{
            print("Video Thumbnail clicked.")
        }label: {
            
            VStack(alignment: .leading) {
                Image("dalek")
                    .renderingMode(.original)
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: 160, height: 90)
                    .clipped()
                    .clipShape(RoundedRectangle(cornerRadius: 10, style: .continuous))
                    .shadow(color: .black.opacity(0.1), radius: 2, x: 0, y: 3)
                HStack{
                    VStack{
                        Image("peach")
                            .resizable()
                            .scaledToFill()
                            .frame(width: 20, height: 20)
                            .clipShape(Circle())
                        Spacer()
                    }
                    
                    VStack{
                        HStack{
                            Text("Video Title")
                                .font(.system(size: 12))
                            Spacer()
                        }
                        HStack{
                            Text("Channel Name")
                                .font(.system(size: 10))
                                .foregroundStyle(.secondary)
                            if verified{
                                Image(systemName: "checkmark.circle.fill")
                                    .font(.system(size: 8))
                                    .foregroundStyle(.secondary)
                            }
                            Spacer()
                        }
                        HStack{
                            Text("123 Views • 1 hour ago")
                                .font(.system(size: 10))
                                .foregroundStyle(.secondary)
                            Spacer()
                        }
                        Spacer()
                    }
                }
                
            }
            .frame(width: 160,height: 150)
            .clipped()
        }
        .buttonStyle(.plain)
    }
}

struct SideBanner: View {
    var body: some View {
        ScrollView(.vertical, showsIndicators: false) {
            VStack {
                NavButton(title: "Home",typeOf: "home", systemNameCh: "house.fill")
                NavButton(title: "Shorts",typeOf: "home", systemNameCh: "play.square.stack")
                NavDivider()
                NavButton(title: "Subscriptions",typeOf: "open", systemNameCh: "chevron.right")
                ForEach(0..<5) { _ in
                    NavButton(title: "Subscription",typeOf: "sub")
                }
                NavDivider()
                NavButton(title: "You",typeOf: "open", systemNameCh: "chevron.right")
                NavButton(title: "History",typeOf: "home",systemNameCh: "clock.arrow.trianglehead.counterclockwise.rotate.90")
                NavButton(title: "Playlists",typeOf: "home",systemNameCh: "list.triangle")
                NavButton(title: "Watch later",typeOf: "home",systemNameCh: "clock")
                NavButton(title: "Liked videos",typeOf: "home",systemNameCh: "hand.thumbsup")
                NavButton(title: "Your Videos",typeOf: "home",systemNameCh: "play.rectangle")
                NavButton(title: "Show More",typeOf: "home",systemNameCh: "chevron.down")
                NavDivider()
                HStack{
                    Text("Explore")
                        .font(.system(size: 8))
                        .foregroundColor(.ytAccent)
                        .padding(5)
                    Spacer()
                }
                
                NavButton(title: "Shopping",typeOf: "home",systemNameCh: "bag")
                NavButton(title: "Music",typeOf: "home",systemNameCh: "music.note")
                NavButton(title: "Movies & TV",typeOf: "home",systemNameCh: "movieclapper")
                NavButton(title: "Show More",typeOf: "home",systemNameCh: "chevron.down")
                NavDivider()
                
                HStack{
                    Text("More from Platform")
                        .font(.system(size: 8))
                        .foregroundColor(.ytAccent)
                        .padding(5)
                    Spacer()
                }
                NavButton(title: "Platform TV",typeOf: "home",systemNameCh: "play.tv",iconColor: .red)
                NavButton(title: "Platform Music",typeOf: "home",systemNameCh: "play.circle.fill",iconColor: .red)
                NavButton(title: "Platform Kids",typeOf: "home",systemNameCh: "play.house.fill",iconColor: .red)
                NavDivider()
                
                NavButton(title: "Report history",typeOf: "home",systemNameCh: "flag")
                NavDivider()
                VStack{
                    Text("About Press Copyright Contact us Creators Advertise Developers\n\nTerms Privacy Policy Status Advertising Choices")
                        .font(.system(size: 6))
                        .foregroundColor(.gray)
                        .padding(5)
                    HStack{
                        Image(systemName: "c.circle")
                            .font(.system(size: 4))
                            .foregroundColor(Color(.darkGray))
                        Text("2026 Platform LLC")
                            .font(.system(size: 4))
                            .foregroundColor(Color(.darkGray))
                    }
                    Spacer()
                }
                
                
            }
            .padding(.horizontal)
        }
            .frame(width: 140)
        
    }
    
}

struct NavDivider: View {
    var body: some View {
        Rectangle()
            .frame(height: 1)
            .foregroundStyle(Color(.ytButton))
            .padding(5)
    }
}

struct NavButton: View {
    var title: String = "Hello there"
    // mode, open
    var typeOf: String = "mode"
    var systemNameCh: String = "house.fill"
    var imageNameCh: String = "peach"
    var iconColor: Color = .ytAccent
    
    var body: some View {
        Button{
            print(title + " clicked.")
        }label: {
            HStack{
                if typeOf == "home"{
                    Image(systemName: systemNameCh)
                        .foregroundColor(iconColor)
                }else if typeOf == "sub"{
                    Image("peach")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 14, height: 14)
                        .clipShape(Circle())
                }
//                else{
//                    Image(systemName: "globe.americas.fill")
//                }
                
                
                Text(title)
                    .padding(.horizontal, 6)
                    .padding(.vertical, 5)
                    .font(.system(size: 8))
                    .foregroundColor(.ytAccent)
                if typeOf == "open"{
                    Image(systemName: systemNameCh)
                        .font(.system(size: 8))
                        .foregroundColor(iconColor)
                }
                Spacer()
            }
        }
        .buttonStyle(.plain)
    }
}

struct FilterButtonBanner: View {
    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack {
                ForEach(0..<10) { _ in
                    FilterButton(title: "Technology")
                }
            }
            .padding(.horizontal)
        }
    }
}

struct FilterButton: View {
    var title: String = "Hello there"
    var body: some View {
        Button{
            print("Filter button, \(title), clicked.")
        }label: {
            Text(title)
                .padding(.horizontal, 6)
                .padding(.vertical, 5)
                .background(
                    Color.ytButton,
                    in: RoundedRectangle(cornerRadius: 4, style: .continuous)
                )
                .font(.system(size: 8))
                .foregroundColor(.ytAccent)
        }
        .buttonStyle(.plain)
    }
}

struct MenuBar: View {
    @State private var text = ""
    var body: some View {
            HStack{
                
                
                Button{
                    print("Menu button clicked.")
                }label: {
                    HStack{
                        Image(systemName: "line.3.horizontal")
                    }
                }
                .buttonStyle(.plain)
                .padding(.horizontal,8)
                
                Button{
                    print("Platform button clicked.")
                }label: {
                    HStack{
                        Image(systemName: "play.rectangle.on.rectangle.fill")
                            .foregroundColor(Color(.red))
                        Text("Platform")
                    }
                }
                .buttonStyle(.plain)
                
                Spacer()
                HStack{
                    ZStack{
                        TextField("Search", text: $text)
                            .clipShape(Capsule())
                        HStack{
                            Spacer()
                            Button{
                                print("Search button, \(text), clicked.")
                            }label: {
                                Image(systemName: "magnifyingglass")
                            }
                            .buttonStyle(.plain)
                            .padding(10)
                        }
                    }
                    Button{
                        print("Mic button clicked.")
                    }label: {
                        Image(systemName: "microphone.fill")
                    }
                    .buttonStyle(.plain)
                }
                    .padding()
                Spacer()
                
                Button{
                    print("Create button clicked.")
                }label: {
                    Image(systemName: "plus")
                    Text("Create")
                }
                .buttonStyle(.plain)
                
                Button{
                    print("Bell button clicked.")
                }label: {
                    Image(systemName: "bell")
                }
                .buttonStyle(.plain)
                
                Button{
                    print("Profile button clicked.")
                }label: {
                    Image("peach")
                        .resizable()
                        .scaledToFill()
                        .frame(width: 20, height: 20)
                        .clipShape(Circle())
                        .padding()
                }
                .buttonStyle(.plain)
            }
            .padding(.horizontal)
    }
}

#Preview {
    YouTubeView()
}