import SwiftUI enum AppSection: String, CaseIterable, Hashable, Identifiable { var id: String { rawValue } case dashboard = "Dashboard" case communications = "Communications" case calendar = "Calendar" case oracle = "Oracle" case sentinel = "Sentinel" case inventory = "Inventory" case settings = "Settings" var systemImage: String { switch self { case .dashboard: return "square.grid.2x2" case .communications: return "phone.connection" case .calendar: return "calendar.badge.clock" case .oracle: return "message.and.waveform" case .sentinel: return "person.crop.rectangle" case .inventory: return "shippingbox" case .settings: return "gearshape" } } var accentColor: Color { switch self { case .dashboard: return VelocityTheme.accent case .communications: return Color(red: 0.19, green: 0.84, blue: 0.63) case .calendar: return Color(red: 0.96, green: 0.67, blue: 0.16) case .oracle: return Color(red: 0.13, green: 0.83, blue: 0.93) // cyan case .sentinel: return Color(red: 0.60, green: 0.57, blue: 0.99) // indigo case .inventory: return VelocityTheme.warning case .settings: return VelocityTheme.mutedFg } } } struct ContentView: View { @State private var selectedSection: AppSection? = .dashboard var body: some View { NavigationSplitView(columnVisibility: .constant(.all)) { sidebarContent } detail: { detailContent } .navigationSplitViewStyle(.balanced) } // MARK: โ€“ Sidebar private var sidebarContent: some View { ZStack { VelocityTheme.sidebarBg.ignoresSafeArea() VStack(spacing: 0) { // App title HStack(spacing: 10) { ZStack { RoundedRectangle(cornerRadius: 9) .fill(VelocityTheme.accent.opacity(0.18)) .frame(width: 34, height: 34) Image(systemName: "bolt.fill") .font(.system(size: 15, weight: .semibold)) .foregroundStyle(VelocityTheme.accent) } VStack(alignment: .leading, spacing: 1) { Text("Velocity") .font(.system(size: 16, weight: .semibold)) .foregroundStyle(VelocityTheme.foreground) Text("Project Velocity ยท v1.1") .font(.system(size: 10)) .foregroundStyle(VelocityTheme.mutedFg) } Spacer() } .padding(.horizontal, 16) .padding(.top, 20) .padding(.bottom, 16) Divider() .background(VelocityTheme.borderSubtle) .padding(.bottom, 8) // Nav items VStack(spacing: 2) { ForEach(AppSection.allCases) { section in SidebarRow(section: section, isSelected: selectedSection == section) .onTapGesture { selectedSection = section } } } .padding(.horizontal, 8) Spacer() // User footer Divider() .background(VelocityTheme.borderSubtle) HStack(spacing: 10) { ZStack { RoundedRectangle(cornerRadius: 8) .fill(VelocityTheme.accent) .frame(width: 32, height: 32) Text("AF") .font(.system(size: 11, weight: .bold)) .foregroundStyle(.white) } VStack(alignment: .leading, spacing: 2) { Text("Ahmed Al-Farsi") .font(.system(size: 12, weight: .medium)) .foregroundStyle(VelocityTheme.foreground) Text("Sales Director") .font(.system(size: 10)) .foregroundStyle(VelocityTheme.mutedFg) } Spacer() } .padding(16) } } .navigationTitle("") .toolbar(.hidden, for: .navigationBar) } // MARK: โ€“ Detail private var detailContent: some View { ZStack { VelocityTheme.background.ignoresSafeArea() Group { switch selectedSection { case .dashboard: DashboardView() case .communications: CommunicationsView() case .calendar: CalendarView() case .oracle: OracleView() case .sentinel: SentinelView() case .inventory: InventoryView() case .settings: SettingsView() case .none: DashboardView() } } .frame(maxWidth: .infinity, maxHeight: .infinity) } } } // MARK: โ€“ Sidebar Row private struct SidebarRow: View { let section: AppSection let isSelected: Bool var body: some View { HStack(spacing: 11) { Image(systemName: section.systemImage) .font(.system(size: 14, weight: .medium)) .foregroundStyle(isSelected ? section.accentColor : VelocityTheme.mutedFg) .frame(width: 20) Text(section.rawValue) .font(.system(size: 14, weight: isSelected ? .semibold : .regular)) .foregroundStyle(isSelected ? VelocityTheme.foreground : VelocityTheme.mutedFg) Spacer() } .padding(.horizontal, 12) .padding(.vertical, 9) .background( RoundedRectangle(cornerRadius: 10) .fill(isSelected ? section.accentColor.opacity(0.12) : .clear) .overlay( RoundedRectangle(cornerRadius: 10) .stroke(isSelected ? section.accentColor.opacity(0.25) : .clear, lineWidth: 1) ) ) .contentShape(Rectangle()) } } #Preview { ContentView() }