// // MeterInfoCardView.swift // USB Meter // import SwiftUI struct MeterInfoCardView: View { let title: String let infoMessage: String? let tint: Color let isCollapsible: Bool @State private var isExpanded: Bool @ViewBuilder var trailingActions: TrailingActions @ViewBuilder var content: Content init( title: String, infoMessage: String? = nil, tint: Color, isCollapsible: Bool = false, initiallyExpanded: Bool = true, @ViewBuilder trailingActions: () -> TrailingActions = { EmptyView() }, @ViewBuilder content: () -> Content ) { self.title = title self.infoMessage = infoMessage self.tint = tint self.isCollapsible = isCollapsible self._isExpanded = State(initialValue: initiallyExpanded) self.trailingActions = trailingActions() self.content = content() } var body: some View { VStack(alignment: .leading, spacing: isExpanded ? 12 : 0) { HStack(spacing: 8) { Text(title) .font(.headline) if let infoMessage { ContextInfoButton(title: title, message: infoMessage) } Spacer(minLength: 0) trailingActions if isCollapsible { Image(systemName: "chevron.up") .font(.caption.weight(.semibold)) .foregroundColor(.secondary) .rotationEffect(.degrees(isExpanded ? 0 : -180)) .animation(.easeInOut(duration: 0.2), value: isExpanded) } } .contentShape(Rectangle()) .onTapGesture { guard isCollapsible else { return } withAnimation(.easeInOut(duration: 0.25)) { isExpanded.toggle() } } if isExpanded { content .transition(.opacity.combined(with: .move(edge: .top))) } } .frame(maxWidth: .infinity, alignment: .leading) .padding(18) .meterCard(tint: tint, fillOpacity: 0.18, strokeOpacity: 0.24) } }