├── .gitattributes ├── Package.swift ├── LICENSE ├── Sources └── ContentBlurView │ └── ContentBlurView.swift ├── .gitignore └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.9 2 | // The swift-tools-version declares the minimum version of Swift required to build this package. 3 | 4 | import PackageDescription 5 | 6 | let package = Package( 7 | name: "ContentBlurView", 8 | platforms: [ 9 | .iOS(.v16), 10 | .watchOS(.v10) 11 | ], 12 | products: [ 13 | // Products define the executables and libraries a package produces, making them visible to other packages. 14 | .library(name: "ContentBlurView", targets: ["ContentBlurView"]), 15 | ], 16 | targets: [ 17 | // Targets are the basic building blocks of a package, defining a module or a test suite. 18 | // Targets can depend on other targets in this package and products from dependencies. 19 | .target(name: "ContentBlurView") 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Hidde van der Ploeg 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Sources/ContentBlurView/ContentBlurView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentBlurView.swift 3 | // ContentBlurView 4 | // For that fancy blur gradient effect as seen in watchOS 10 5 | // 6 | // Created by @hiddevdploeg on 20/07/2023. 7 | // 8 | 9 | import SwiftUI 10 | public struct ContentBlurView: View{ 11 | 12 | @ViewBuilder var content: () -> Content 13 | @State private var direction : BlurDirection 14 | 15 | 16 | public init(direction: BlurDirection = .bottomBlur, content: @escaping () -> Content) { 17 | self.direction = direction 18 | self.content = content 19 | } 20 | 21 | public var body: some View { 22 | ZStack { 23 | 24 | content() 25 | 26 | Rectangle() 27 | .fill(Color.clear) 28 | .background(Material.ultraThin) 29 | .mask { 30 | LinearGradient(colors: [ 31 | Color.black.opacity(0), 32 | Color.black.opacity(0.1), 33 | Color.black.opacity(0.5), 34 | Color.black.opacity(0.75), 35 | Color.black.opacity(1), 36 | Color.black.opacity(1), 37 | Color.black.opacity(1), 38 | Color.black.opacity(1), 39 | ], 40 | startPoint: direction.start, 41 | endPoint: direction.end) 42 | } 43 | } 44 | } 45 | } 46 | 47 | 48 | public enum BlurDirection { 49 | case bottomBlur, topBlur, leadingBlur, trailingBlur 50 | 51 | var start: UnitPoint { 52 | switch self { 53 | case .bottomBlur: 54 | .top 55 | case .topBlur: 56 | .bottom 57 | case .leadingBlur: 58 | .trailing 59 | case .trailingBlur: 60 | .leading 61 | } 62 | } 63 | 64 | var end: UnitPoint { 65 | switch self { 66 | case .bottomBlur: 67 | .bottom 68 | case .topBlur: 69 | .top 70 | case .leadingBlur: 71 | .leading 72 | case .trailingBlur: 73 | .trailing 74 | } 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## User settings 6 | xcuserdata/ 7 | 8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 9 | *.xcscmblueprint 10 | *.xccheckout 11 | 12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 13 | build/ 14 | DerivedData/ 15 | *.moved-aside 16 | *.pbxuser 17 | !default.pbxuser 18 | *.mode1v3 19 | !default.mode1v3 20 | *.mode2v3 21 | !default.mode2v3 22 | *.perspectivev3 23 | !default.perspectivev3 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | 28 | ## App packaging 29 | *.ipa 30 | *.dSYM.zip 31 | *.dSYM 32 | 33 | ## Playgrounds 34 | timeline.xctimeline 35 | playground.xcworkspace 36 | 37 | # Swift Package Manager 38 | # 39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. 40 | # Packages/ 41 | # Package.pins 42 | # Package.resolved 43 | # *.xcodeproj 44 | # 45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 46 | # hence it is not needed unless you have added a package configuration file to your project 47 | # .swiftpm 48 | 49 | .build/ 50 | 51 | # CocoaPods 52 | # 53 | # We recommend against adding the Pods directory to your .gitignore. However 54 | # you should judge for yourself, the pros and cons are mentioned at: 55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 56 | # 57 | # Pods/ 58 | # 59 | # Add this line if you want to avoid checking in source code from the Xcode workspace 60 | # *.xcworkspace 61 | 62 | # Carthage 63 | # 64 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 65 | # Carthage/Checkouts 66 | 67 | Carthage/Build/ 68 | 69 | # Accio dependency management 70 | Dependencies/ 71 | .accio/ 72 | 73 | # fastlane 74 | # 75 | # It is recommended to not store the screenshots in the git repo. 76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed. 77 | # For more information about the recommended setup visit: 78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 79 | 80 | fastlane/report.xml 81 | fastlane/Preview.html 82 | fastlane/screenshots/**/*.png 83 | fastlane/test_output 84 | 85 | # Code Injection 86 | # 87 | # After new code Injection tools there's a generated folder /iOSInjectionProject 88 | # https://github.com/johnno1962/injectionforxcode 89 | 90 | iOSInjectionProject/ 91 | .DS_Store 92 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ContentBlurView 2 | Easily get a fancy looking gradient blur as seen on watchOS 10 3 | 4 | Example 5 | 6 | 7 | ## Installation 8 | Ready to use on iOS 17+ or watchOS 10+. 9 | 10 | 1. In Xcode, select **Add Packages…** from the File menu. 11 | 2. Enter `https://github.com/hiddevdploeg/ContentBlurView` in the search field. 12 | 3. Click **Add Package** (Set the Dependency Rule to Up to Next Major Version) 13 | 4. After adding the package, you will be able to import ContentBlurView in your project by using. 14 | 15 | ```swift 16 | import ContentBlurView 17 | ``` 18 | 19 | ## How use 20 | 21 | You can use `ContentBlurView` with any `View` 22 | 23 | ```swift 24 | ContentBlurView { 25 | // Any view goes here 26 | } 27 | .ignoresSafeArea(edges: .all) // for fullscreen enjoyment 28 | 29 | ``` 30 | 31 | ### Directions 32 | You can decide on which side the blur should start: `.topBlur`, `.leadingBlur`, `trailingBlur` or `.bottomBlur`. the default is `.bottomBlur` 33 | 34 | ### Text 35 | It's recommended to use [`HierarchicalShapeStyle`](https://developer.apple.com/documentation/swiftui/hierarchicalshapestyle) as a `.foregroundStyle` of your text as this will make it more vibrant with the background. 36 | 37 | 38 | **Examples** 39 | 40 | ```swift 41 | 42 | import MapKit 43 | struct ContentView: View { 44 | var body: some View { 45 | TabView { 46 | 47 | // Example with image and blur on top 48 | ContentBlurView(direction: .topBlur) { 49 | AsyncImage(url: URL(string: "https://picsum.photos/800")) 50 | } 51 | .ignoresSafeArea(edges: .all) 52 | 53 | // Example with Map and text on top of it 54 | ZStack(alignment: .bottom) { 55 | ContentBlurView { 56 | Map(interactionModes: .rotate) { 57 | Marker("Apple Park", coordinate: CLLocationCoordinate2D(latitude: 37.334268, longitude: -122.008715)) 58 | } 59 | .mapStyle(.imagery) 60 | } 61 | .ignoresSafeArea(edges: .all) 62 | Text("Apple Park") 63 | .font(.headline) 64 | .foregroundStyle(.primary) 65 | .padding() 66 | } 67 | } 68 | .tabViewStyle(.verticalPage) 69 | } 70 | } 71 | 72 | ``` 73 | 74 | ## Authors 75 | This library is created by [Hidde van der Ploeg](https://hidde.design). Feel free to reach out on [Twitter](https://twitter.com/hiddevdploeg) or [Mastodon](https://mastodon.design/@hidde). 76 | 77 | ## License 78 | ContentBlurView is available under the MIT license. 79 | 80 | 81 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 82 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 83 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 84 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 85 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 86 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 87 | --------------------------------------------------------------------------------