1 contributor
//
// MeterInfoCardView.swift
// USB Meter
//
import SwiftUI
struct MeterInfoCardView<Content: View, TrailingActions: View>: 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)
}
}