import SwiftUI import SFSafeSymbols private struct ListPopup: View { @Environment(\.dismiss) var dismiss let items: [String] var body: some View { VStack { List { ForEach(items, id: \.self) { page in Text(page) } } .frame(minHeight: min(CGFloat(items.count) * 31, 500)) Button("Dismiss") { dismiss() } } .padding(.vertical) .onTapGesture { dismiss() } } } private struct TextWithPopup: View { let symbol: SFSymbol let text: LocalizedStringKey let items: [String] @State private var isHovering = false var body: some View { HStack { Image(systemSymbol: symbol) .resizable() .aspectRatio(contentMode: .fit) .frame(width: 16, height: 16) Text(text) } .contentShape(Rectangle()) .onTapGesture { if items.count > 0 { isHovering.toggle() } } .sheet(isPresented: $isHovering) { ListPopup(items: items) .onTapGesture { isHovering.toggle() } } } } struct PageContentResultsView: View { @Environment(\.language) private var language @ObservedObject var results: PageGenerationResults var body: some View { HStack { TextWithPopup( symbol: .photoOnRectangleAngled, text: "\(results.files.count + results.missingFiles.count) images and files", items: results.files.sorted().map { $0.id }) .foregroundStyle(.secondary) TextWithPopup( symbol: .docBadgePlus, text: "\(results.linkedPages.count + results.missingPages.count) page links", items: results.linkedPages.sorted().map { $0.localized(in: language).title }) .foregroundStyle(.secondary) TextWithPopup( symbol: .globe, text: "\(results.externalLinks.count) external links", items: results.externalLinks.sorted()) .foregroundStyle(.secondary) if !results.missingPages.isEmpty { TextWithPopup( symbol: .exclamationmarkTriangleFill, text: "\(results.missingPages.count) missing pages", items: results.missingPages.sorted()) .foregroundStyle(.red) } if !results.missingFiles.isEmpty { TextWithPopup( symbol: .exclamationmarkTriangleFill, text: "\(results.missingFiles.count) missing files", items: results.missingFiles.sorted()) .foregroundStyle(.red) } if !results.invalidCommands.isEmpty { TextWithPopup( symbol: .exclamationmarkTriangleFill, text: "\(results.invalidCommands.count) invalid commands", items: results.invalidCommands.map { $0.markdown }.sorted()) .foregroundStyle(.red) } } } } #Preview { PageContentResultsView(results: .init()) }