import SwiftUI struct EditorTabBar: View { @ObservedObject var editorState: EditorState var body: some View { ScrollView(.horizontal, showsIndicators: false) { HStack(spacing: 0) { ForEach(editorState.tabs) { tab in EditorTabCell( tab: tab, isActive: tab.id == editorState.activeTabId, onSelect: { editorState.activeTabId = tab.id }, onClose: { editorState.closeTab(id: tab.id) } ) } } } .frame(height: 36) .background(Color(.secondarySystemBackground)) .overlay(alignment: .bottom) { Divider() } } } struct EditorTabCell: View { let tab: EditorTab let isActive: Bool let onSelect: () -> Void let onClose: () -> Void @State private var isHovered = false var body: some View { HStack(spacing: 6) { if tab.isDirty { Circle().fill(Color.accentColor).frame(width: 6, height: 6) } else { Button(action: onClose) { Image(systemName: "xmark").font(.system(size: 9, weight: .semibold)) .frame(width: 14, height: 14).contentShape(Circle()) } .buttonStyle(.plain) .opacity((isActive || isHovered) ? 1 : 0) } Image(systemName: fileIcon(for: tab.fileName)) .font(.system(size: 11)).foregroundStyle(iconColor(for: tab.fileName)) Text(tab.fileName) .font(.system(.caption, design: .monospaced)).lineLimit(1) } .padding(.horizontal, 10).frame(height: 36) .background(isActive ? Color(.systemBackground) : .clear) .overlay(alignment: .bottom) { if isActive { Rectangle().fill(Color.accentColor).frame(height: 2) } } .contentShape(Rectangle()) .onTapGesture(perform: onSelect) .onHover { isHovered = $0 } } private func fileIcon(for name: String) -> String { switch (name as NSString).pathExtension.lowercased() { case "swift": return "swift"; case "json": return "curlybraces" case "md": return "doc.text"; case "sh": return "terminal"; default: return "doc" } } private func iconColor(for name: String) -> Color { switch (name as NSString).pathExtension.lowercased() { case "swift": return .orange; case "json": return .yellow case "md": return .blue; default: return .secondary } } }