CardList.swift 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. //
  2. // CardList.swift
  3. // LoopKitUI
  4. //
  5. // Created by Michael Pangburn on 4/10/20.
  6. // Copyright © 2020 LoopKit Authors. All rights reserved.
  7. //
  8. import SwiftUI
  9. public struct CardListSection: View {
  10. var title: Text?
  11. var stack: CardStack
  12. public init(title: Text? = nil, @CardStackBuilder cards: () -> CardStack) {
  13. self.title = title
  14. self.stack = cards()
  15. }
  16. public var body: some View {
  17. VStack(spacing: 6) {
  18. if let title = title {
  19. HStack {
  20. title
  21. .font(Font(UIFont.preferredFont(forTextStyle: .title3)))
  22. .bold()
  23. Spacer()
  24. }
  25. .padding(.leading)
  26. }
  27. stack
  28. }
  29. }
  30. }
  31. public enum CardListStyle {
  32. case simple(CardStack)
  33. case sectioned([CardListSection])
  34. }
  35. /// Displays a list of cards similar to a `List` with an inset grouped style,
  36. /// but without the baggage of `UITableViewCell` resizing, enabling cells to expand smoothly.
  37. public struct CardList<Trailer: View>: View {
  38. var title: Text?
  39. var style: CardListStyle
  40. var trailer: Trailer?
  41. public init(title: Text? = nil, style: CardListStyle, trailer: Trailer) {
  42. self.title = title
  43. self.style = style
  44. self.trailer = trailer
  45. }
  46. public init(title: Text? = nil, style: CardListStyle) where Trailer == EmptyView {
  47. self.title = title
  48. self.style = style
  49. self.trailer = nil
  50. }
  51. public var body: some View {
  52. ScrollView {
  53. VStack(spacing: 4) {
  54. titleText
  55. .fixedSize(horizontal: false, vertical: true)
  56. cards
  57. if let trailer = trailer {
  58. trailer
  59. }
  60. }
  61. }
  62. .background(Color(.systemGroupedBackground))
  63. }
  64. @ViewBuilder
  65. private var titleText: some View {
  66. if let title = title {
  67. HStack {
  68. title
  69. .font(.largeTitle)
  70. .bold()
  71. Spacer()
  72. }
  73. .padding()
  74. .padding(.bottom, 4)
  75. .background(Color(.systemGroupedBackground))
  76. } else {
  77. Spacer()
  78. }
  79. }
  80. private var cards: some View {
  81. switch style {
  82. case .simple(let stack):
  83. return AnyView(stack)
  84. case .sectioned(let sections):
  85. return AnyView(
  86. VStack(spacing: 16) {
  87. ForEach(Array(sections.enumerated()), id: \.offset) { index, section in
  88. section
  89. }
  90. }
  91. )
  92. }
  93. }
  94. }