import SwiftUI struct CategoryPillBar: View { @Binding var selected: AppSection var streamCount: Int = 0 var totalGames: Int = 0 var liveGames: Int = 0 @Namespace private var selectionNamespace private var primarySections: [AppSection] { AppSection.allCases.filter { $0 != .settings } } var body: some View { ViewThatFits { expandedBar compactBar } } private var expandedBar: some View { HStack(spacing: 24) { brandLockup HStack(spacing: 10) { ForEach(primarySections) { section in sectionButton(section) } } Spacer(minLength: 12) HStack(spacing: 10) { statusChip(value: "\(liveGames)", label: "Live", systemImage: "dot.radiowaves.left.and.right", tint: DS.Colors.live) statusChip(value: "\(totalGames)", label: "Games", systemImage: "sportscourt", tint: DS.Colors.media) statusChip(value: "\(streamCount)", label: "Tiles", systemImage: "rectangle.split.2x2", tint: DS.Colors.positive) settingsButton } } .padding(.horizontal, containerPadH) .padding(.vertical, containerPadV) .background(shellBackground) } private var compactBar: some View { VStack(alignment: .leading, spacing: 16) { HStack(spacing: 16) { brandLockup Spacer() settingsButton } ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 10) { ForEach(primarySections) { section in sectionButton(section) } statusChip(value: "\(liveGames)", label: "Live", systemImage: "dot.radiowaves.left.and.right", tint: DS.Colors.live) statusChip(value: "\(totalGames)", label: "Games", systemImage: "sportscourt", tint: DS.Colors.media) statusChip(value: "\(streamCount)", label: "Tiles", systemImage: "rectangle.split.2x2", tint: DS.Colors.positive) } } .scrollClipDisabled() } .padding(.horizontal, containerPadH) .padding(.vertical, containerPadV) .background(shellBackground) } private var brandLockup: some View { VStack(alignment: .leading, spacing: 3) { Text("MLB") .font(brandPrimaryFont) .foregroundStyle(DS.Colors.textPrimary) Text("CONTROL ROOM") .font(brandSecondaryFont) .foregroundStyle(DS.Colors.textTertiary) .tracking(brandTracking) } } private func sectionButton(_ section: AppSection) -> some View { Button { withAnimation(.spring(response: 0.36, dampingFraction: 0.82)) { selected = section } } label: { HStack(spacing: 10) { Image(systemName: section.systemImage) .font(.system(size: iconSize, weight: .bold)) Text(section.title) .font(pillFont) } .foregroundStyle(selected == section ? Color.black.opacity(0.86) : DS.Colors.textSecondary) .padding(.horizontal, pillPadH) .padding(.vertical, pillPadV) .background { if selected == section { Capsule() .fill( LinearGradient( colors: [ DS.Colors.interactive, DS.Colors.warning, ], startPoint: .topLeading, endPoint: .bottomTrailing ) ) .matchedGeometryEffect(id: "selected-section", in: selectionNamespace) } else { Capsule() .fill(DS.Colors.panelFillMuted) } } } .platformCardStyle() } private var settingsButton: some View { Button { selected = .settings } label: { Image(systemName: "gearshape.fill") .font(.system(size: iconSize, weight: .bold)) .foregroundStyle(selected == .settings ? Color.black.opacity(0.86) : DS.Colors.textSecondary) .padding(.horizontal, pillPadH) .padding(.vertical, pillPadV) .background { if selected == .settings { Capsule() .fill( LinearGradient( colors: [ DS.Colors.interactive, DS.Colors.warning, ], startPoint: .topLeading, endPoint: .bottomTrailing ) ) } else { Capsule() .fill(DS.Colors.panelFillMuted) } } } .platformCardStyle() } private func statusChip(value: String, label: String, systemImage: String, tint: Color) -> some View { HStack(spacing: 9) { Image(systemName: systemImage) .font(.system(size: statIconSize, weight: .bold)) .foregroundStyle(tint) Text(value) .font(statValueFont) .foregroundStyle(DS.Colors.textPrimary) .monospacedDigit() Text(label) .font(statLabelFont) .foregroundStyle(DS.Colors.textTertiary) } .padding(.horizontal, statPadH) .padding(.vertical, statPadV) .background( Capsule() .fill(DS.Colors.panelFillMuted) .overlay { Capsule() .strokeBorder(DS.Colors.panelStroke, lineWidth: 1) } ) } private var shellBackground: some View { RoundedRectangle(cornerRadius: shellRadius, style: .continuous) .fill(DS.Colors.navFill) .overlay { RoundedRectangle(cornerRadius: shellRadius, style: .continuous) .strokeBorder(DS.Colors.panelStroke, lineWidth: 1) } .shadow(color: DS.Shadows.card, radius: DS.Shadows.cardRadius, y: DS.Shadows.cardY) } #if os(tvOS) private var shellRadius: CGFloat { 28 } private var containerPadH: CGFloat { 28 } private var containerPadV: CGFloat { 22 } private var pillPadH: CGFloat { 24 } private var pillPadV: CGFloat { 16 } private var statPadH: CGFloat { 18 } private var statPadV: CGFloat { 14 } private var pillFont: Font { .system(size: 23, weight: .bold, design: .rounded) } private var statValueFont: Font { .system(size: 22, weight: .black, design: .rounded) } private var statLabelFont: Font { .system(size: 16, weight: .bold, design: .rounded) } private var brandPrimaryFont: Font { .system(size: 34, weight: .black, design: .rounded) } private var brandSecondaryFont: Font { .system(size: 14, weight: .black, design: .rounded) } private var brandTracking: CGFloat { 2.6 } private var iconSize: CGFloat { 20 } private var statIconSize: CGFloat { 13 } #else private var shellRadius: CGFloat { 22 } private var containerPadH: CGFloat { 18 } private var containerPadV: CGFloat { 16 } private var pillPadH: CGFloat { 18 } private var pillPadV: CGFloat { 10 } private var statPadH: CGFloat { 12 } private var statPadV: CGFloat { 10 } private var pillFont: Font { .system(size: 15, weight: .bold, design: .rounded) } private var statValueFont: Font { .system(size: 15, weight: .black, design: .rounded) } private var statLabelFont: Font { .system(size: 11, weight: .bold, design: .rounded) } private var brandPrimaryFont: Font { .system(size: 20, weight: .black, design: .rounded) } private var brandSecondaryFont: Font { .system(size: 10, weight: .black, design: .rounded) } private var brandTracking: CGFloat { 1.8 } private var iconSize: CGFloat { 15 } private var statIconSize: CGFloat { 11 } #endif } enum AppSection: String, CaseIterable, Identifiable { case today case intel case highlights case multiView case settings var id: String { rawValue } var title: String { switch self { case .today: "Dashboard" case .intel: "League" case .highlights: "Highlights" case .multiView: "Multi-View" case .settings: "Settings" } } var systemImage: String { switch self { case .today: "rectangle.3.group.fill" case .intel: "chart.xyaxis.line" case .highlights: "play.rectangle.on.rectangle.fill" case .multiView: "rectangle.split.2x2.fill" case .settings: "gearshape.fill" } } }