Created
February 16, 2025 14:17
-
-
Save juliensagot/ea5bd3d951b09cf6593d3885f2fbfb23 to your computer and use it in GitHub Desktop.
Revisions
-
juliensagot created this gist
Feb 16, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,196 @@ import SwiftUI struct AquaScrollBar: View { @ScaledMetric private var height = 35.0 var body: some View { Track() .frame(height: height) .overlay(alignment: .leading) { Thumb() .containerRelativeFrame(.horizontal) { length, axis in length / 3 } .padding(1) .foregroundStyle(.tint) .padding(.leading, 32) } .mask { Capsule() } } } private struct Thumb: View { @State private var size: CGSize? var body: some View { Rectangle() .fill(.tint) .overlay( Rectangle() .fill( .linearGradient( stops: [ .init(color: .black.opacity(0.4), location: 0.0), .init(color: .black.opacity(0), location: 0.9) ], startPoint: .top, endPoint: .bottom ) ) .blendMode(.plusDarker) ) .overlay( Rectangle() .fill( .linearGradient( stops: [ .init(color: .white.opacity(0.0), location: 0.0), .init(color: .white.opacity(0.86), location: 1.0) ], startPoint: .top, endPoint: .bottom ) ) .blendMode(.overlay) ) .drawingGroup() .overlay( HStack(spacing: 14) { ForEach(0...3, id: \.self) { i in Rectangle() .fill( .linearGradient( stops: [ .init(color: .white.opacity(0.2), location: 0.0), .init(color: .white, location: 1.0) ], startPoint: .top, endPoint: .bottom ) ) } } .padding(.horizontal, 6) .opacity(0.06) .blur(radius: 4) .blendMode(.plusLighter) ) .overlay( LinearGradient( stops: [ .init(color: .white.opacity(0), location: 0.8), .init(color: .white.opacity(0.3), location: 0.9), .init(color: .white.opacity(1.0), location: 1.0) ], startPoint: .top, endPoint: .bottom ) .opacity(0.8) ) .overlay(alignment: .top) { Capsule() .fill( .linearGradient( stops: [ .init(color: .white.opacity(0.8), location: 0.0), .init(color: .white.opacity(0.1), location: 1.0) ], startPoint: .top, endPoint: .bottom ) ) .blendMode(.plusLighter) .overlay( Capsule() .strokeBorder( .linearGradient( stops: [ .init(color: .white.opacity(0.3), location: 0.0), .init(color: .white.opacity(0), location: 0.2) ], startPoint: .top, endPoint: .bottom ), lineWidth: 1 ) ) .frame(height: (size?.height).flatMap({ $0 / 2.3 })) .padding(.horizontal, 8) .padding(.top, 2) } .overlay( ContainerRelativeShape() .stroke( .linearGradient( colors: [.black.opacity(0.1), .black.opacity(0.4)], startPoint: .top, endPoint: .bottom ), lineWidth: 1.5 ) .blendMode(.multiply) ) .clipShape(ContainerRelativeShape()) .containerShape(Capsule()) .brightness(0.03) .shadow( color: .black.opacity(0.26), radius: 4, x: 0, y: 2 ) .onGeometryChange(for: CGSize.self) { geometry in geometry.size } action: { newValue in size = newValue } } } private struct Track: View { var body: some View { ContainerRelativeShape() .fill( .linearGradient( stops: [ .init(color: .black.mix(with: .white, by: 0.86), location: 0.0), .init(color: .white, location: 0.8) ], startPoint: .top, endPoint: .bottom ) .shadow( .inner( color: .black.opacity(0.2), radius: 4, x: 0, y: 4 ) ) ) .overlay( ContainerRelativeShape() .stroke(.black.opacity(0.1), lineWidth: 1.5) ) .mask { ContainerRelativeShape() } .containerShape(Capsule()) } } private extension Color { static var aqua: Self { return .init(red: 62/255, green: 99/255, blue: 165/255) } } #Preview { VStack(spacing: 16) { AquaScrollBar() .tint(Color.aqua) } .padding(.horizontal, 64) }