AppBannerView.swift 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. // LoopFollow
  2. // AppBannerView.swift
  3. import SwiftUI
  4. /// Dismissable banner shown at the top of the app, above the tab content.
  5. struct AppBannerView: View {
  6. let message: BannerMessage
  7. var body: some View {
  8. HStack(alignment: .top, spacing: 12) {
  9. Image(systemName: iconName)
  10. .font(.title3)
  11. .foregroundColor(iconColor)
  12. Text(message.text)
  13. .font(.callout)
  14. .lineLimit(3)
  15. .fixedSize(horizontal: false, vertical: true)
  16. .frame(maxWidth: .infinity, alignment: .leading)
  17. Button {
  18. BannerManager.shared.dismissCurrent()
  19. } label: {
  20. Image(systemName: "xmark.circle.fill")
  21. .font(.title3)
  22. .foregroundColor(.secondary)
  23. }
  24. .accessibilityLabel("Dismiss")
  25. }
  26. .padding()
  27. .background(
  28. RoundedRectangle(cornerRadius: 12, style: .continuous)
  29. .fill(tint)
  30. )
  31. .overlay(
  32. RoundedRectangle(cornerRadius: 12, style: .continuous)
  33. .stroke(border, lineWidth: 1)
  34. )
  35. .padding(.horizontal, 10)
  36. .padding(.vertical, 4)
  37. }
  38. private var iconName: String {
  39. switch message.severity {
  40. case .info: return "info.circle.fill"
  41. case .warning: return "exclamationmark.triangle.fill"
  42. case .error: return "xmark.octagon.fill"
  43. }
  44. }
  45. private var iconColor: Color {
  46. switch message.severity {
  47. case .info: return .blue
  48. case .warning: return .orange
  49. case .error: return .red
  50. }
  51. }
  52. private var tint: Color {
  53. switch message.severity {
  54. case .info: return Color.blue.opacity(0.20)
  55. case .warning: return Color.orange.opacity(0.20)
  56. case .error: return Color.red.opacity(0.20)
  57. }
  58. }
  59. private var border: Color {
  60. switch message.severity {
  61. case .info: return Color.blue.opacity(0.40)
  62. case .warning: return Color.orange.opacity(0.40)
  63. case .error: return Color.red.opacity(0.40)
  64. }
  65. }
  66. }