import SwiftUI struct RangeSliderView: View { @Binding var lowerBound: Double @Binding var upperBound: Double private let thumbSize: CGFloat = 24 private let trackHeight: CGFloat = 6 private let minimumGap: Double = 0.02 var body: some View { GeometryReader { geometry in let width = geometry.size.width - thumbSize ZStack(alignment: .leading) { // Background track Capsule() .fill(Color(UIColor.systemGray4)) .frame(height: trackHeight) .padding(.horizontal, thumbSize / 2) // Selected range Capsule() .fill(Color.accentColor) .frame( width: CGFloat(upperBound - lowerBound) * width, height: trackHeight ) .offset(x: thumbSize / 2 + CGFloat(lowerBound) * width) // Lower thumb thumb() .offset(x: CGFloat(lowerBound) * width) .gesture( DragGesture() .onChanged { value in let new = Double(value.location.x / width) lowerBound = min(max(new, 0), upperBound - minimumGap) } ) // Upper thumb thumb() .offset(x: CGFloat(upperBound) * width) .gesture( DragGesture() .onChanged { value in let new = Double(value.location.x / width) upperBound = max(min(new, 1), lowerBound + minimumGap) } ) } .frame(height: 44) } .frame(height: 44) } private func thumb() -> some View { Circle() .fill(.white) .shadow(color: .black.opacity(0.15), radius: 3, y: 1) .frame(width: thumbSize, height: thumbSize) .contentShape(Rectangle().size(width: 44, height: 44)) } }