ContentUnavailableView.swift 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /// An interface, consisting of a label and additional content,
  2. /// that you display when the content of your app is unavailable to users.
  3. public struct ContentUnavailableView<Label: View, Description: View, Actions: View>: View {
  4. /// Creates an interface, consisting of a label and additional content,
  5. /// that you display when the content of your app is unavailable to users.
  6. ///
  7. /// - Parameters:
  8. /// - label: The label that describes the view.
  9. /// - description: The view giving more information about the reason
  10. /// for the content being unavailable.
  11. /// - actions: The view containing actions related to the content being unavailable.
  12. /// For example "Back to Home", "Login" or "Refresh".
  13. public init(
  14. @ViewBuilder label: () -> Label,
  15. @ViewBuilder description: () -> Description = { EmptyView() },
  16. @ViewBuilder actions: () -> Actions = { EmptyView() }
  17. ) {
  18. self.label = label()
  19. self.description = description()
  20. self.actions = actions()
  21. }
  22. private var label: Label
  23. private var description: Description
  24. private var actions: Actions
  25. @Environment(\.backend) var backend
  26. @Environment(\.foregroundColor) var environmentForegroundColor
  27. var labelFont: Font {
  28. switch backend.deviceClass.kind {
  29. case .phone, .tablet, .watch: .title2
  30. case .tv: .headline
  31. case .desktop: .largeTitle
  32. }
  33. }
  34. var descriptionFont: Font {
  35. switch backend.deviceClass.kind {
  36. case .phone, .tablet, .tv, .watch: .subheadline
  37. case .desktop: .body
  38. }
  39. }
  40. var labelColor: Color {
  41. if let environmentForegroundColor { return environmentForegroundColor }
  42. if backend.deviceClass == .desktop { return .gray }
  43. return .adaptive(light: .black, dark: .white)
  44. }
  45. public var body: some View {
  46. VStack {
  47. label
  48. .font(labelFont)
  49. .foregroundColor(labelColor)
  50. description
  51. .font(descriptionFont)
  52. .foregroundColor(environmentForegroundColor ?? .gray)
  53. if backend.deviceClass == .desktop {
  54. HStack {
  55. actions
  56. .font(.body)
  57. .foregroundColor(
  58. environmentForegroundColor
  59. ?? .adaptive(light: .black, dark: .white)
  60. )
  61. }
  62. } else {
  63. VStack {
  64. actions
  65. .font(.body)
  66. }
  67. }
  68. }
  69. .if(backend.deviceClass != .desktop) { view in
  70. view.padding(30)
  71. }
  72. .if(backend.deviceClass == .desktop) { view in
  73. view.frame(maxWidth: 360)
  74. }
  75. }
  76. }