listless

A simple list app for Apple platforms
Log | Files | Refs | README | LICENSE

PullToCreate.swift (2152B)


      1 import SwiftUI
      2 
      3 struct PullToCreateIndicator: View {
      4     let pullOffset: CGFloat
      5     let threshold: CGFloat
      6     @AppStorage("colorTheme") private var colorThemeRaw = 0
      7     private var colorTheme: ColorTheme { ColorTheme(rawValue: colorThemeRaw) ?? .pilbara }
      8 
      9     static let indicatorHeight: CGFloat = 50
     10 
     11     private var isReady: Bool { pullOffset >= threshold }
     12     private let textSlideDistance: CGFloat = 22
     13 
     14     var body: some View {
     15         HStack(alignment: .center, spacing: ItemRowMetrics.contentSpacing) {
     16             Image(systemName: "circle")
     17                 .frame(width: 22, height: 22)
     18                 .foregroundStyle(Color.secondary)
     19                 .font(.system(size: 17))
     20             ZStack(alignment: .leading) {
     21                 Text("Release to add")
     22                     .offset(y: isReady ? 0 : -textSlideDistance)
     23                 Text("New item")
     24                     .offset(y: isReady ? textSlideDistance : 0)
     25             }
     26             .foregroundStyle(.secondary)
     27             .font(ItemRowMetrics.bodySUI)
     28             .frame(height: textSlideDistance, alignment: .topLeading)
     29             .clipped()
     30             .animation(.easeInOut(duration: 0.18), value: isReady)
     31             Spacer()
     32         }
     33         .padding(.vertical, ItemRowMetrics.contentVerticalPadding)
     34         .padding(.trailing, ItemRowMetrics.contentHorizontalPadding)
     35         .padding(.leading, ItemRowMetrics.activeLeadingPadding)
     36         .frame(maxWidth: .infinity, alignment: .leading)
     37         .contentShape(Rectangle())
     38         .background(Color.itemCard)
     39         .clipShape(
     40             UnevenRoundedRectangle(
     41                 topLeadingRadius: 0, bottomLeadingRadius: 0,
     42                 bottomTrailingRadius: ItemRowMetrics.trailingCornerRadius,
     43                 topTrailingRadius: ItemRowMetrics.trailingCornerRadius
     44             )
     45         )
     46         .overlay(alignment: .leading) {
     47             Rectangle()
     48                 .fill(itemColor(forIndex: 0, total: 1, theme: colorTheme))
     49                 .frame(width: ItemRowMetrics.accentBarWidth)
     50         }
     51         .frame(height: Self.indicatorHeight, alignment: .top)
     52         .allowsHitTesting(false)
     53     }
     54 }