├── .github ├── FUNDING.yml └── workflows │ ├── swiftlint.yml │ ├── build-multiplatform.yml │ ├── build-documentation.yml │ └── tests.yml ├── .spi.yml ├── .swiftlint.yml ├── Tests └── ColorsTests │ └── ColorsTests.swift ├── Package.swift ├── LICENCE.md ├── .gitignore ├── Sources └── Colors │ ├── ColorExtractor.swift │ ├── Colors.swift │ └── BaseColors.swift ├── README.md └── .spm.swift /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: 0xWDG 2 | -------------------------------------------------------------------------------- /.spi.yml: -------------------------------------------------------------------------------- 1 | version: 1 2 | builder: 3 | configs: 4 | - documentation_targets: [SwiftUI-Color] -------------------------------------------------------------------------------- /.swiftlint.yml: -------------------------------------------------------------------------------- 1 | excluded: 2 | - "*resource_bundle_accessor*" # SwiftPM Generated 3 | - ".build/*" 4 | 5 | opt_in_rules: 6 | - missing_docs 7 | - empty_count 8 | - empty_string 9 | - toggle_bool 10 | - unused_optional_binding 11 | - valid_ibinspectable 12 | - modifier_order 13 | - first_where 14 | - fatal_error_message 15 | - force_unwrapping 16 | 17 | -------------------------------------------------------------------------------- /.github/workflows/swiftlint.yml: -------------------------------------------------------------------------------- 1 | name: Run Swiftlint 2 | on: 3 | push: 4 | pull_request: 5 | workflow_dispatch: 6 | 7 | jobs: 8 | swiftlint: 9 | runs-on: macos-latest 10 | steps: 11 | - uses: actions/checkout@v3 12 | 13 | - name: SwiftLint 14 | run: | 15 | brew install swiftlint 16 | swiftlint --reporter github-actions-logging --strict -------------------------------------------------------------------------------- /.github/workflows/build-multiplatform.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/build-multiplatform.yml 2 | 3 | name: Build-Packages 4 | 5 | on: 6 | # Run on pull_request 7 | pull_request: 8 | 9 | # Dispatch if triggered using Github (website) 10 | workflow_dispatch: 11 | 12 | jobs: 13 | Build-Packages: 14 | runs-on: macos-latest 15 | steps: 16 | - name: Build Swift Packages 17 | uses: 0xWDG/build-swift@main -------------------------------------------------------------------------------- /.github/workflows/build-documentation.yml: -------------------------------------------------------------------------------- 1 | # .github/workflows/build-documentation.yml 2 | 3 | name: build-documentation 4 | 5 | on: 6 | # Run on push to main branch 7 | push: 8 | branches: 9 | - main 10 | 11 | # Dispatch if triggered using Github (website) 12 | workflow_dispatch: 13 | 14 | jobs: 15 | Build-documentation: 16 | runs-on: macos-latest 17 | steps: 18 | - name: Build documentation 19 | uses: 0xWDG/build-documentation@main 20 | -------------------------------------------------------------------------------- /.github/workflows/tests.yml: -------------------------------------------------------------------------------- 1 | name: Run tests on Linux and macOS 2 | on: 3 | push: 4 | workflow_dispatch: 5 | 6 | jobs: 7 | test_linux: 8 | if: false 9 | runs-on: ubuntu-latest 10 | continue-on-error: true 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Swift test 15 | run: swift test 16 | 17 | test_macos: 18 | runs-on: macos-latest 19 | steps: 20 | - uses: actions/checkout@v3 21 | 22 | - name: Swift test 23 | run: swift test 24 | -------------------------------------------------------------------------------- /Tests/ColorsTests/ColorsTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorsTests.swift 3 | // Colors 4 | // 5 | // Created by Wesley de Groot on 2024-08-22. 6 | // https://wesleydegroot.nl 7 | // 8 | // https://github.com/0xWDG/SwiftUI-Color 9 | // MIT License 10 | // 11 | import XCTest 12 | @testable import Colors 13 | 14 | final class ColorsTests: XCTestCase { 15 | func testExample() throws { 16 | // XCTest Documentation 17 | // https://developer.apple.com/documentation/xctest 18 | 19 | // Defining Test Cases and Test Methods 20 | // https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Package.swift: -------------------------------------------------------------------------------- 1 | // swift-tools-version: 5.8.0 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: "Colors", 8 | platforms: [ 9 | .iOS(.v14), 10 | .macOS(.v11), 11 | .watchOS(.v6), 12 | .tvOS(.v13) 13 | ], 14 | products: [ 15 | // Products define the executables and libraries a package produces, making them visible to other packages. 16 | .library( 17 | name: "Colors", 18 | targets: ["Colors"]) 19 | ], 20 | targets: [ 21 | // Targets are the basic building blocks of a package, defining a module or a test suite. 22 | // Targets can depend on other targets in this package and products from dependencies. 23 | .target( 24 | name: "Colors"), 25 | .testTarget( 26 | name: "ColorsTests", 27 | dependencies: ["Colors"]) 28 | ] 29 | ) 30 | -------------------------------------------------------------------------------- /LICENCE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Wesley de Groot, email@WesleydeGroot.nl 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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## User settings 2 | xcuserdata/ 3 | 4 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) 5 | *.xcscmblueprint 6 | *.xccheckout 7 | 8 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) 9 | build/ 10 | DerivedData/ 11 | *.moved-aside 12 | *.pbxuser 13 | !default.pbxuser 14 | *.mode1v3 15 | !default.mode1v3 16 | *.mode2v3 17 | !default.mode2v3 18 | *.perspectivev3 19 | !default.perspectivev3 20 | 21 | ## Obj-C/Swift specific 22 | *.hmap 23 | 24 | ## App packaging 25 | *.ipa 26 | *.dSYM.zip 27 | *.dSYM 28 | 29 | ## Playgrounds 30 | timeline.xctimeline 31 | playground.xcworkspace 32 | 33 | ### Swift Package Manager 34 | Packages/ 35 | Package.pins 36 | Package.resolved 37 | # *.xcodeproj 38 | # 39 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata 40 | # hence it is not needed unless you have added a package configuration file to your project 41 | .swiftpm 42 | .build/ 43 | 44 | ### CocoaPods 45 | Pods/ 46 | *.xcworkspace 47 | 48 | ### Carthage 49 | Carthage/Checkouts 50 | Carthage/Build/ 51 | 52 | ### Accio dependency management 53 | Dependencies/ 54 | .accio/ 55 | 56 | ### fastlane 57 | fastlane/report.xml 58 | fastlane/Preview.html 59 | fastlane/screenshots/**/*.png 60 | fastlane/test_output 61 | 62 | ### Code Injection 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /Sources/Colors/ColorExtractor.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ColorExtractor.swift 3 | // Colors 4 | // 5 | // Created by Wesley de Groot on 16/09/2024. 6 | // https://wesleydegroot.nl 7 | // 8 | // https://github.com/0xWDG/SwiftUI-Color 9 | // MIT License 10 | // 11 | 12 | #if canImport(SwiftUI) && (canImport(UIKit) || canImport(AppKit)) 13 | import SwiftUI 14 | 15 | #if canImport(AppKit) 16 | /// SystemColor to NSColor typealias 17 | public typealias SystemColor = NSColor 18 | #elseif canImport(UIKit) 19 | /// SystemColor to UIColor typealias 20 | public typealias SystemColor = UIColor 21 | #endif 22 | 23 | extension SystemColor { 24 | /// Extract dark mode color 25 | public var dark: SystemColor { 26 | #if canImport(UIKit) 27 | #if os(watchOS) 28 | // Since watchOS does not have dark/lightmode we just return the color. 29 | self 30 | #else 31 | resolvedColor(with: .init(userInterfaceStyle: .dark)) 32 | #endif 33 | #else 34 | var value: SystemColor? 35 | 36 | NSAppearance( 37 | named: .darkAqua 38 | )?.performAsCurrentDrawingAppearance { 39 | value = self 40 | } 41 | 42 | // Dirty way to wait for the result, is there a better way? 43 | while value == nil {} 44 | 45 | return value! 46 | // swiftlint:disable:previous force_unwrapping 47 | #endif 48 | } 49 | 50 | /// Extract light mode color 51 | public var light: SystemColor { 52 | #if canImport(UIKit) 53 | #if os(watchOS) 54 | // Since watchOS does not have dark/lightmode we just return the color. 55 | self 56 | #else 57 | resolvedColor(with: .init(userInterfaceStyle: .light)) 58 | #endif 59 | #else 60 | var value: SystemColor? 61 | 62 | NSAppearance( 63 | named: .aqua 64 | )?.performAsCurrentDrawingAppearance { 65 | value = self 66 | } 67 | 68 | // Dirty way to wait for the result, is there a better way? 69 | while value == nil {} 70 | 71 | return value! 72 | // swiftlint:disable:previous force_unwrapping 73 | #endif 74 | } 75 | 76 | /// get the .init for BaseColors 77 | var baseColorsInit: String { 78 | return String( 79 | format: ".init(red: %.2f, green: %.2f, blue: %.2f, alpha: %.2f)", 80 | self.redValue, self.greenValue, self.blueValue, self.alphaValue 81 | ) 82 | } 83 | 84 | /// Get the hex string of the current color 85 | public var hex: String { 86 | return String( 87 | format: "#%02x%02x%02x%02x", 88 | Int(self.redValue * 255), 89 | Int(self.greenValue * 255), 90 | Int(self.blueValue * 255), 91 | Int(self.alphaValue * 255) 92 | ) 93 | } 94 | 95 | /// Get the red value component of the color 96 | public var redValue: CGFloat { 97 | return self.cgColor.components?[0] ?? 0 98 | } 99 | 100 | /// Get the green value component of the color 101 | public var greenValue: CGFloat { 102 | return self.cgColor.components?[1] ?? 0 103 | } 104 | 105 | /// Get the blue value component of the color 106 | public var blueValue: CGFloat { 107 | return self.cgColor.components?[2] ?? 0 108 | } 109 | 110 | /// Get the alpha value component of the color 111 | public var alphaValue: CGFloat { 112 | return self.cgColor.components?[3] ?? 0 113 | } 114 | 115 | /// Create initializer for (BaseColors.swift) 116 | /// 117 | /// - Parameter color: Color name 118 | /// - Returns: Color initializer 119 | /// 120 | /// Usage in **UIKit**: 121 | /// ```swift 122 | /// UIColor.systemPink.createInitializerFor(color: "systemPink") 123 | /// ``` 124 | /// 125 | /// Usage in **AppKit**: 126 | /// ```swift 127 | /// NSColor.systemPink.createInitializerFor(color: "systemPink") 128 | /// ``` 129 | /// 130 | /// Returns: 131 | /// ```swift 132 | /// /// A color that represents the system-provided systemPink color. 133 | /// public static let systemPink = Color.dynamicColor( 134 | /// light: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00), 135 | /// dark: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00) 136 | /// ) 137 | /// ``` 138 | public func createInitializerFor(color name: String) -> String { 139 | return """ 140 | /// A color that represents the system-provided \(name) color. 141 | public static let \(name) = Color.dynamicColor( 142 | light: \(self.light.baseColorsInit), 143 | dark: \(self.dark.baseColorsInit) 144 | ) 145 | """ 146 | } 147 | } 148 | #endif 149 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Colors 2 | 3 | Colors is a Swift Package to enable all system colors in SwiftUI trough a `Color` extension. 4 | Colors which were previously only available in `UIColor`/`NSColor` are now available in `Color` as well. 5 | 6 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F0xWDG%2FColors%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/0xWDG/Colors) 7 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F0xWDG%2FColors%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/0xWDG/Colors) 8 | [![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://swift.org/package-manager) 9 | ![License](https://img.shields.io/github/license/0xWDG/Colors) 10 | 11 | Available colors are: `lightText`, `darkText`, `placeholderText`, `label`, `secondaryLabel`, `tertiaryLabel`, `quaternaryLabel`, `systemBackground`, `secondarySystemBackground`, `tertiarySystemBackground`, `systemFill`, `secondarySystemFill`, `tertiarySystemFill`, `quaternarySystemFill`, `systemGroupedBackground`, `secondarySystemGroupedBackground`, `tertiarySystemGroupedBackground`, `systemGray`, `systemGray2`, `systemGray3`, `systemGray4`, `systemGray5`, `systemGray6`, `separator`, `opaqueSeparator`, `link`, `systemBlue`, `systemCyan`, `systemMint`, `systemPurple`, `systemGreen`, `systemYellow`, `systemOrange`, `systemPink`, `systemRed`, `systemTeal`, `systemIndigo`, `scrubberTexturedBackground`, `textBackgroundColor`, `controlTextColor`, `quaternaryLabelColor`, `findHighlightColor`, `highlightColor`, `shadowColor`, `windowFrameTextColor`, `windowBackgroundColor`, `keyboardFocusIndicatorColor`, `separatorColor`, `selectedControlColor`, `controlBackgroundColor`, `secondaryLabelColor`, `tertiaryLabelColor`, `gridColor`, `alternateSelectedControlTextColor`, `unemphasizedSelectedContentBackgroundColor`, `textColor`, `systemBrown`, `selectedContentBackgroundColor`, `selectedTextColor`, `labelColor`, `placeholderTextColor`, `unemphasizedSelectedTextBackgroundColor`, `disabledControlTextColor`, `headerTextColor`, `linkColor`, `selectedTextBackgroundColor`, `unemphasizedSelectedTextColor`, `controlColor`, `selectedControlTextColor`, `underPageBackgroundColor`, `selectedMenuItemTextColor`. 12 | 13 | ## Requirements 14 | 15 | - Swift 5.9+ (Xcode 15+) 16 | - iOS 13+, macOS 10.15+ 17 | 18 | ## Installation (Pakage.swift) 19 | 20 | ```swift 21 | dependencies: [ 22 | .package(url: "https://github.com/0xWDG/Colors.git", branch: "main"), 23 | ], 24 | targets: [ 25 | .target(name: "MyTarget", dependencies: [ 26 | .product(name: "Colors", package: "Colors"), 27 | ]), 28 | ] 29 | ``` 30 | 31 | ## Installation (Xcode) 32 | 33 | 1. In Xcode, open your project and navigate to **File** → **Swift Packages** → **Add Package Dependency...** 34 | 2. Paste the repository URL (`https://github.com/0xWDG/Colors`) and click **Next**. 35 | 3. Click **Finish**. 36 | 37 | ## Usage 38 | 39 | ```swift 40 | import SwiftUI 41 | import Colors 42 | 43 | struct ContentView: View { 44 | var body: some View { 45 | VStack { 46 | Text("Hello, World!") 47 | .foregroundColor(Color.disabledControlTextColor) 48 | } 49 | .padding() 50 | } 51 | } 52 | ``` 53 | 54 | ## Extract color from UIColor/NSColor 55 | 56 | Use this to add new/missing colors to the `BaseColor` and `Color` extension. 57 | 58 | Extract from **UIKit**: 59 | ```swift 60 | UIColor.systemPink.createInitializerFor(color: "systemPink") 61 | ``` 62 | 63 | Extract from **AppKit**: 64 | ```swift 65 | NSColor.systemPink.createInitializerFor(color: "systemPink") 66 | ``` 67 | 68 | Output: 69 | ```swift 70 | /// A color that represents the system-provided systemPink color. 71 | public static let systemPink = Color.dynamicColor( 72 | light: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00), 73 | dark: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00) 74 | ) 75 | ``` 76 | 77 | ## How to add a new color 78 | 79 | 1. Add the color to the `BaseColor` struct. 80 | ```swift 81 | /// A color that represents the system-provided systemPink color. 82 | public static let systemPink = Color.dynamicColor( 83 | light: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00), 84 | dark: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1.00) 85 | ) 86 | ``` 87 | 2. Add the color to the `Color` extension. 88 | - Use the native `Color`,`NSColor`,`UIColor.colorName` where possible. 89 | - Add #if os(iOS) / #if os(macOS) where needed. 90 | - Example (works on almost all versions): 91 | ```swift 92 | /// A color that represents the system-provided pink color. 93 | public static var systemPink: Color { 94 | #if os(iOS) || os(tvOS) 95 | Color(UIColor.systemPink) 96 | #elseif os(macOS) 97 | Color(NSColor.systemPink) 98 | #else 99 | BaseColor.systemPink 100 | #endif 101 | } 102 | ``` 103 | - Example 2 (works from a specific iOS/macOS version): 104 | ```swift 105 | /// A color that represents the system-provided cyan color. 106 | public static var systemCyan: Color { 107 | #if os(iOS) || os(tvOS) 108 | if #available(iOS 15.0, *) { 109 | Color(UIColor.systemCyan) 110 | } else { 111 | BaseColor.systemCyan 112 | } 113 | #elseif os(macOS) 114 | if #available(macOS 12.0, *) { 115 | Color(NSColor.systemCyan) 116 | } else { 117 | BaseColor.systemCyan 118 | } 119 | #else 120 | BaseColor.systemCyan 121 | #endif 122 | } 123 | ``` 124 | 125 | ## Contact 126 | 127 | 🦋 [@0xWDG](https://bsky.app/profile/0xWDG.bsky.social) 128 | 🐘 [mastodon.social/@0xWDG](https://mastodon.social/@0xWDG) 129 | 🐦 [@0xWDG](https://x.com/0xWDG) 130 | 🧵 [@0xWDG](https://www.threads.net/@0xWDG) 131 | 🌐 [wesleydegroot.nl](https://wesleydegroot.nl) 132 | 🤖 [Discord](https://discordapp.com/users/918438083861573692) 133 | 134 | Interested learning more about Swift? [Check out my blog](https://wesleydegroot.nl/blog/). 135 | -------------------------------------------------------------------------------- /.spm.swift: -------------------------------------------------------------------------------- 1 | #!/usr/bin/swift 2 | 3 | // 4 | // spm.swift 5 | // This script will add a header to all .swift files in the current directory. 6 | // And can test the package for various platforms. 7 | // 8 | // Created by Wesley de Groot on 2024-08-06. 9 | // https://wesleydegroot.nl 10 | // 11 | // https://github.com/0xWDG/spm-template 12 | // MIT License 13 | 14 | // To compile this script to a binary, run: 15 | // swiftc .spm.swift -o spm 16 | 17 | // swiftlint:disable all 18 | import Foundation 19 | 20 | let fileManager = FileManager.default 21 | var internalProductName: String? 22 | var productName: String { 23 | get { 24 | if let productName = internalProductName { 25 | return productName 26 | } 27 | 28 | if fileManager.fileExists(atPath: "Package.swift") { 29 | guard let package = try? String(contentsOf: URL(fileURLWithPath: "Package.swift"), encoding: .utf8), 30 | let productName = package 31 | .components(separatedBy: .newlines) 32 | .first(where: { $0.contains("name:") })? 33 | .components(separatedBy: .whitespaces) 34 | .last? 35 | .replacingOccurrences(of: "\"", with: "") 36 | .replacingOccurrences(of: ",", with: "") else { 37 | printC("Could not find product name in Package.swift", color: CLIColors.red) 38 | exit(2) 39 | } 40 | 41 | return productName 42 | } else { 43 | printC("Package.swift not found, please provide package name", color: CLIColors.red) 44 | return "" 45 | } 46 | } 47 | set { 48 | internalProductName = newValue 49 | } 50 | } 51 | 52 | struct CLIColors { 53 | static let red = "\u{001B}[0;31m" 54 | static let green = "\u{001B}[0;32m" 55 | static let yellow = "\u{001B}[0;33m" 56 | static let orange = "\u{001B}[0;38;5;208m" 57 | static let blue = "\u{001B}[0;34m" 58 | static let magenta = "\u{001B}[0;35m" 59 | static let cyan = "\u{001B}[0;36m" 60 | static let white = "\u{001B}[0;37m" 61 | static let reset = "\u{001B}[0;0m" 62 | static let clear = "\u{001B}[0;0m" 63 | } 64 | 65 | func printUsage() { 66 | print("Usage: \(CommandLine.arguments[0]) ") 67 | print("Commands:") 68 | print(" create - Add a header to all .swift files in the current directory") 69 | print(" header - Update the header for all .swift files in the current directory") 70 | print(" readme - Generate a README.md file for the package") 71 | print(" build - Build the package for all platforms") 72 | print(" test - Test the package for all platforms") 73 | } 74 | 75 | func printC(_ text: String, terminator: String = "\n", color: String = CLIColors.reset) { 76 | if terminator == "\n" { 77 | print("\(color)\(text) \(CLIColors.reset)") 78 | } else { 79 | print("\(color)\(text)\(CLIColors.reset)", terminator: terminator) 80 | fflush(stdout) 81 | } 82 | } 83 | 84 | if CommandLine.argc < 2 { 85 | printUsage() 86 | exit(1) 87 | } 88 | 89 | if CommandLine.arguments[1] == "create" && CommandLine.argc < 3 { 90 | print("Usage: \(CommandLine.arguments[0]) create ") 91 | exit(1) 92 | } 93 | 94 | if CommandLine.arguments[1] == "create" && CommandLine.argc == 3 { 95 | productName = CommandLine.arguments[2] 96 | 97 | if !fileManager.fileExists(atPath: "Package.swift") { 98 | let process = Process() 99 | process.launchPath = "/usr/bin/env" 100 | process.arguments = ["swift", "package", "init", "--name", productName] 101 | process.launch() 102 | process.waitUntilExit() 103 | } 104 | 105 | /// Change the first line of the Package.swift file 106 | let package = try String(contentsOf: URL(fileURLWithPath: "Package.swift"), encoding: .utf8) 107 | let newPackage = package 108 | .components(separatedBy: .newlines) 109 | .enumerated() 110 | .map { index, line in 111 | if index == 0 { 112 | return "// swift-tools-version: 5.8.0" 113 | } else { 114 | return line 115 | } 116 | } 117 | .joined(separator: "\n") 118 | try? newPackage.write(to: URL(fileURLWithPath: "Package.swift"), atomically: true, encoding: .utf8) 119 | printC("Downgraded swift-tools-version to 5.8.0", color: CLIColors.green) 120 | 121 | let spi = """ 122 | version: 1 123 | builder: 124 | configs: 125 | - documentation_targets: [\(productName)] 126 | """ 127 | try spi.write(to: URL(fileURLWithPath: ".spi.yml"), atomically: true, encoding: .utf8) 128 | 129 | header() 130 | generateReadme() 131 | } 132 | 133 | if CommandLine.arguments[1] == "header" { 134 | header() 135 | } 136 | 137 | if CommandLine.arguments[1] == "readme" { 138 | generateReadme() 139 | } 140 | 141 | if CommandLine.arguments[1] == "build" { 142 | if !fileManager.fileExists(atPath: "Package.swift") { 143 | printC("Package.swift not found", color: CLIColors.red) 144 | exit(2) 145 | } 146 | 147 | // Find platforms in Package.swift 148 | let package = try String(contentsOf: URL(fileURLWithPath: "Package.swift"), encoding: .utf8) 149 | var platforms: [String] = [] 150 | var fails = 0 151 | 152 | if package.contains(".iOS") { 153 | platforms.append("iOS") 154 | } 155 | 156 | if package.contains(".macOS") { 157 | platforms.append("macOS") 158 | } 159 | 160 | if package.contains(".watchOS") { 161 | platforms.append("watchOS") 162 | } 163 | 164 | if package.contains(".visionOS") { 165 | platforms.append("xrOS") 166 | } 167 | 168 | if package.contains(".tvOS") { 169 | platforms.append("tvOS") 170 | } 171 | 172 | if package.contains(".maccatalyst") { 173 | platforms.append("MacCatalyst") 174 | } 175 | 176 | if package.contains(".driverkit") { 177 | printC("DriverKit is not supported, skipped", color: CLIColors.orange) 178 | // platforms.append("DriverKit") 179 | } 180 | 181 | if package.contains(".linux") { 182 | printC("Linux is not supported, skipped", color: CLIColors.orange) 183 | // platforms.append("Linux") 184 | } 185 | 186 | if package.contains(".android") { 187 | printC("Android is not supported, skipped", color: CLIColors.orange) 188 | // platforms.append("Android") 189 | } 190 | 191 | if platforms.isEmpty { 192 | printC("No platforms found in Package.swift, defaulting to all", color: CLIColors.orange) 193 | platforms = ["iOS", "tvOS", "xrOS", "watchOS", "macOS"] 194 | } 195 | 196 | printC("Build \(productName) for \(platforms.joined(separator: ", "))...") 197 | 198 | for (number, platform) in platforms.enumerated() { 199 | printC("Building \(productName) on \(platform). (\(number + 1)/\(platforms.count))", terminator: "\r") 200 | let process = Process() 201 | process.launchPath = "/usr/bin/env" 202 | process.arguments = [ 203 | "xcrun", 204 | "xcodebuild", 205 | "clean", 206 | "build", 207 | "-quiet", 208 | "-scheme", productName, 209 | "-destination", "generic/platform=\(platform)" 210 | ] 211 | process.launch() 212 | process.waitUntilExit() 213 | // Check if the process was successful 214 | if process.terminationStatus != 0 { 215 | fails += 1 216 | printC("Failed to build for \(platform) (\(number + 1)/\(platforms.count))", color: CLIColors.red) 217 | } else { 218 | printC("Build for \(platform) successful (\(number + 1)/\(platforms.count)) ", color: CLIColors.green) 219 | } 220 | } 221 | 222 | if fails > 0 { 223 | printC("Failed to build for \(fails) platforms", color: CLIColors.red) 224 | } else { 225 | printC("Build for all platforms successful", color: CLIColors.green) 226 | } 227 | 228 | exit(0) 229 | } 230 | 231 | if CommandLine.arguments[1] == "test" { 232 | printC("Testing is not yet implemented", color: CLIColors.red) 233 | exit(99) 234 | } 235 | 236 | func header() { 237 | // Search for all .swift files 238 | let enumerator = fileManager.enumerator(atPath: ".") 239 | while let element = enumerator?.nextObject() as? String { 240 | if element.hasSuffix(".swift") { 241 | var headerLines = 0 242 | 243 | let dateFormatter = DateFormatter() 244 | dateFormatter.dateFormat = "yyyy-MM-dd" 245 | let date = dateFormatter.string(from: Date()) 246 | 247 | var createdBy = "// Created by Wesley de Groot on \(date)." 248 | let file = element 249 | let path = URL(fileURLWithPath: file) 250 | guard let contents = try? String(contentsOf: path, encoding: .utf8) else { 251 | printC("Failed to read \(file)", color: CLIColors.red) 252 | continue 253 | } 254 | let filename = file.components(separatedBy: "/").last 255 | var lines = contents.components(separatedBy: .newlines) 256 | 257 | if lines.isEmpty { 258 | break 259 | } 260 | 261 | if lines[0].hasPrefix("#!") || file == "Package.swift" { 262 | continue 263 | } 264 | 265 | for line in lines { 266 | if line.hasPrefix("//") { 267 | if line.contains("Created by") { 268 | createdBy = line 269 | } 270 | 271 | headerLines += 1 272 | } else { 273 | break 274 | } 275 | } 276 | 277 | lines.removeFirst(Int(headerLines)) 278 | 279 | let header = [ 280 | "//", 281 | "// \(filename ?? "")", 282 | "// \(productName)", 283 | "//", 284 | createdBy, 285 | "// https://wesleydegroot.nl", 286 | "//", 287 | "// https://github.com/0xWDG/\(productName)", 288 | "// MIT License", 289 | "//" 290 | ] 291 | 292 | lines.insert(contentsOf: header, at: 0) 293 | let newContents = lines.joined(separator: "\n") 294 | do { 295 | try newContents.write(to: path, atomically: true, encoding: .utf8) 296 | printC("Updated header for \(file)", color: CLIColors.green) 297 | } catch { 298 | printC("Failed to update header for \(file)", color: CLIColors.red) 299 | } 300 | } 301 | } 302 | } 303 | 304 | func generateReadme() { 305 | var readme = """ 306 | # PACKAGENAME 307 | 308 | PACKAGENAME is a Swift Package for ... 309 | 310 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F0xWDG%2FPACKAGENAME%2Fbadge%3Ftype%3Dplatforms)](https://swiftpackageindex.com/0xWDG/PACKAGENAME) 311 | [![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2F0xWDG%2FPACKAGENAME%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/0xWDG/PACKAGENAME) 312 | [![Swift Package Manager](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://swift.org/package-manager) 313 | ![License](https://img.shields.io/github/license/0xWDG/PACKAGENAME) 314 | 315 | ## Requirements 316 | 317 | - Swift 5.9+ (Xcode 15+) 318 | - iOS 13+, macOS 10.15+ 319 | 320 | ## Installation (Pakage.swift) 321 | 322 | ```swift 323 | dependencies: [ 324 | .package(url: "https://github.com/0xWDG/PACKAGENAME.git", branch: "main"), 325 | ], 326 | targets: [ 327 | .target(name: "MyTarget", dependencies: [ 328 | .product(name: "PACKAGENAME", package: "PACKAGENAME"), 329 | ]), 330 | ] 331 | ``` 332 | 333 | ## Installation (Xcode) 334 | 335 | 1. In Xcode, open your project and navigate to **File** → **Swift Packages** → **Add Package Dependency...** 336 | 2. Paste the repository URL (`https://github.com/0xWDG/PACKAGENAME`) and click **Next**. 337 | 3. Click **Finish**. 338 | 339 | ## Usage 340 | 341 | ```swift 342 | import SwiftUI 343 | import PACKAGENAME 344 | 345 | struct ContentView: View { 346 | var body: some View { 347 | VStack { 348 | /// ... 349 | } 350 | .padding() 351 | } 352 | } 353 | ``` 354 | 355 | ## Contact 356 | 357 | We can get in touch via [Mastodon](https://mastodon.social/@0xWDG), [Twitter/X](https://twitter.com/0xWDG), [Discord](https://discordapp.com/users/918438083861573692), [Email](mailto:email@wesleydegroot.nl), [Website](https://wesleydegroot.nl). 358 | 359 | Interested learning more about Swift? [Check out my blog](https://wesleydegroot.nl/blog/). 360 | """ 361 | 362 | readme = readme.replacingOccurrences(of: "PACKAGENAME", with: productName) 363 | 364 | try? readme.write(to: URL(fileURLWithPath: "README.md"), atomically: true, encoding: .utf8) 365 | } 366 | 367 | if CommandLine.arguments[1] != "executable" { 368 | let process = Process() 369 | process.launchPath = "/usr/bin/env" 370 | process.arguments = ["swiftc", CommandLine.arguments[0], "-o", "spm"] 371 | process.launch() 372 | process.waitUntilExit() 373 | 374 | if process.terminationStatus != 0 { 375 | printC("Failed to compile script", color: CLIColors.red) 376 | exit(4) 377 | } else { 378 | printC("Script compiled successfully", color: CLIColors.green) 379 | } 380 | } 381 | // swiftlint:enable all 382 | -------------------------------------------------------------------------------- /Sources/Colors/Colors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // Colors 4 | // 5 | // Created by Wesley de Groot on 2024-08-22. 6 | // https://wesleydegroot.nl 7 | // 8 | // https://github.com/0xWDG/SwiftUI-Color 9 | // MIT License 10 | // 11 | 12 | #if canImport(SwiftUI) 13 | import SwiftUI 14 | 15 | extension Color { 16 | // MARK: - iOS: Text Colors 17 | /// A color that represents the system-provided text color. 18 | /// 19 | /// Use this color for text in a standard state, such as a label in a navigation bar or a system button. 20 | /// 21 | /// - Note: When possible, we recommend using `labelColor` and its variants, instead. 22 | public static var lightText: Color { 23 | #if os(iOS) 24 | Color(UIColor.lightText) 25 | #else 26 | BaseColor.lightText 27 | #endif 28 | } 29 | 30 | /// A color that represents the system-provided text color. 31 | /// 32 | /// Use this color for text in a standard state, such as a label in a navigation bar or a system button. 33 | /// 34 | /// - Note: When possible, we recommend using `labelColor` and its variants, instead. 35 | public static var darkText: Color { 36 | #if os(iOS) 37 | Color(UIColor.darkText) 38 | #else 39 | BaseColor.darkText 40 | #endif 41 | } 42 | 43 | /// Foreground color for placeholder text in controls or text fields or text views. 44 | /// 45 | /// Use this color for placeholder text in controls or text views. 46 | public static var placeholderText: Color { 47 | #if os(iOS) 48 | Color(UIColor.placeholderText) 49 | #else 50 | BaseColor.placeholderText 51 | #endif 52 | } 53 | 54 | // MARK: - iOS: Label Colors 55 | /// A color that represents the system-provided label color. 56 | /// 57 | /// Use this color for standard text labels. 58 | public static var label: Color { 59 | #if os(iOS) || os(tvOS) 60 | Color(UIColor.label) 61 | #else 62 | BaseColor.label 63 | #endif 64 | } 65 | 66 | /// A color that represents the system-provided secondary label color. 67 | /// 68 | /// Use this color for text labels that contain secondary content. 69 | public static var secondaryLabel: Color { 70 | #if os(iOS) || os(tvOS) 71 | Color(UIColor.secondaryLabel) 72 | #else 73 | BaseColor.secondaryLabel 74 | #endif 75 | } 76 | 77 | /// A color that represents the system-provided tertiary label color. 78 | /// 79 | /// Use this color for text labels that contain tertiary content. 80 | public static var tertiaryLabel: Color { 81 | #if os(iOS) || os(tvOS) 82 | Color(UIColor.tertiaryLabel) 83 | #else 84 | BaseColor.tertiaryLabel 85 | #endif 86 | } 87 | 88 | /// A color that represents the system-provided quaternary label color. 89 | /// 90 | /// Use this color for text labels that contain quaternary content. 91 | public static var quaternaryLabel: Color { 92 | #if os(iOS) || os(tvOS) 93 | Color(UIColor.quaternaryLabel) 94 | #else 95 | BaseColor.quaternaryLabel 96 | #endif 97 | } 98 | 99 | // MARK: - iOS: Background Colors 100 | /// A color that represents the system-provided background color. 101 | /// 102 | /// Use this color for the main background of your interface. 103 | public static var systemBackground: Color { 104 | #if os(iOS) 105 | Color(UIColor.systemBackground) 106 | #else 107 | BaseColor.systemBackground 108 | #endif 109 | } 110 | 111 | /// A color that represents the system-provided secondary background color. 112 | /// 113 | /// Use this color for content layered on top of the main background. 114 | public static var secondarySystemBackground: Color { 115 | #if os(iOS) 116 | Color(UIColor.secondarySystemBackground) 117 | #else 118 | BaseColor.secondarySystemBackground 119 | #endif 120 | } 121 | 122 | /// A color that represents the system-provided tertiary background color. 123 | /// 124 | /// Use this color for content layered on top of secondary backgrounds. 125 | public static var tertiarySystemBackground: Color { 126 | #if os(iOS) 127 | Color(UIColor.tertiarySystemBackground) 128 | #else 129 | BaseColor.tertiarySystemBackground 130 | #endif 131 | } 132 | 133 | // MARK: - iOS: Fill Colors 134 | /// systemFillColor is appropriate for filling thin and small shapes. 135 | /// 136 | /// Example: The track of a slider. 137 | public static var systemFill: Color { 138 | #if os(iOS) 139 | Color(UIColor.systemFill) 140 | #else 141 | BaseColor.systemFill 142 | #endif 143 | } 144 | 145 | /// secondarySystemFillColor is appropriate for filling medium-size shapes. 146 | /// 147 | /// Example: The background of a switch. 148 | public static var secondarySystemFill: Color { 149 | #if os(iOS) 150 | Color(UIColor.secondarySystemFill) 151 | #else 152 | BaseColor.secondarySystemFill 153 | #endif 154 | } 155 | 156 | /// tertiarySystemFillColor is appropriate for filling large shapes. 157 | /// 158 | /// Examples: Input fields, search bars, buttons. 159 | public static var tertiarySystemFill: Color { 160 | #if os(iOS) 161 | Color(UIColor.tertiarySystemFill) 162 | #else 163 | BaseColor.tertiarySystemFill 164 | #endif 165 | } 166 | 167 | /// quaternarySystemFillColor is appropriate for filling large areas containing complex content. 168 | /// 169 | /// Example: Expanded table cells. 170 | public static var quaternarySystemFill: Color { 171 | #if os(iOS) 172 | Color(UIColor.quaternarySystemFill) 173 | #else 174 | BaseColor.quaternarySystemFill 175 | #endif 176 | } 177 | 178 | // MARK: - iOS: Grouped Background Colors 179 | /// A color that represents the system-provided grouped background color. 180 | /// 181 | /// Use this color for the main background in a grouped interface, such as a grouped table view. 182 | public static var systemGroupedBackground: Color { 183 | #if os(iOS) 184 | Color(UIColor.systemGroupedBackground) 185 | #else 186 | BaseColor.systemGroupedBackground 187 | #endif 188 | } 189 | 190 | /// A color that represents the system-provided secondary grouped background color. 191 | /// 192 | /// Use this color for content layered on top of the main grouped background. 193 | public static var secondarySystemGroupedBackground: Color { 194 | #if os(iOS) 195 | Color(UIColor.secondarySystemBackground) 196 | #else 197 | BaseColor.secondarySystemBackground 198 | #endif 199 | } 200 | 201 | /// A color that represents the system-provided tertiary grouped background color. 202 | /// 203 | /// Use this color for content layered on top of secondary grouped backgrounds. 204 | public static var tertiarySystemGroupedBackground: Color { 205 | #if os(iOS) 206 | Color(UIColor.tertiarySystemGroupedBackground) 207 | #else 208 | BaseColor.tertiarySystemGroupedBackground 209 | #endif 210 | } 211 | 212 | // MARK: - iOS: Gray Colors 213 | /// A color that represents the system-provided gray color. 214 | /// 215 | /// Use this color for standard text labels. 216 | public static var systemGray: Color { 217 | #if os(iOS) || os(tvOS) 218 | Color(UIColor.systemGray) 219 | #elseif os(macOS) 220 | Color(NSColor.systemGray) 221 | #else 222 | BaseColor.systemGray 223 | #endif 224 | } 225 | 226 | /// A color that represents the system-provided gray2 color. 227 | /// 228 | /// Use this color for text labels that contain secondary content. 229 | public static var systemGray2: Color { 230 | #if os(iOS) 231 | Color(UIColor.systemGray2) 232 | #else 233 | BaseColor.systemGray2 234 | #endif 235 | } 236 | 237 | /// A color that represents the system-provided gray3 color. 238 | /// 239 | /// Use this color for text labels that contain tertiary content. 240 | public static var systemGray3: Color { 241 | #if os(iOS) 242 | Color(UIColor.systemGray3) 243 | #else 244 | BaseColor.systemGray3 245 | #endif 246 | } 247 | 248 | /// A color that represents the system-provided gray4 color. 249 | /// 250 | /// Use this color for text labels that contain quaternary content. 251 | public static var systemGray4: Color { 252 | #if os(iOS) 253 | Color(UIColor.systemGray4) 254 | #else 255 | BaseColor.systemGray4 256 | #endif 257 | } 258 | 259 | /// A color that represents the system-provided gray5 color. 260 | /// 261 | /// Use this color for text labels that contain quinary content. 262 | public static var systemGray5: Color { 263 | #if os(iOS) 264 | Color(UIColor.systemGray5) 265 | #else 266 | BaseColor.systemGray5 267 | #endif 268 | } 269 | 270 | /// A color that represents the system-provided gray6 color. 271 | /// 272 | /// Use this color for text labels that contain senary content. 273 | public static var systemGray6: Color { 274 | #if os(iOS) 275 | Color(UIColor.systemGray6) 276 | #else 277 | BaseColor.systemGray6 278 | #endif 279 | } 280 | 281 | // MARK: - iOS: Other Colors 282 | /// A color that represents the system-provided separator color. 283 | /// 284 | /// Use this color for thin borders or divider lines that allows some underlying content to be visible. 285 | public static var separator: Color { 286 | #if os(iOS) || os(tvOS) 287 | Color(UIColor.separator) 288 | #else 289 | BaseColor.separator 290 | #endif 291 | } 292 | 293 | /// A color that represents the system-provided opaque separator color. 294 | /// 295 | /// Use this color for borders or divider lines that are opaque. 296 | public static var opaqueSeparator: Color { 297 | #if os(iOS) || os(tvOS) 298 | Color(UIColor.opaqueSeparator) 299 | #else 300 | BaseColor.opaqueSeparator 301 | #endif 302 | } 303 | 304 | /// A color that represents the system-provided link color. 305 | /// 306 | /// Use this color for links. 307 | public static var link: Color { 308 | #if os(iOS) || os(tvOS) 309 | Color(UIColor.link) 310 | #else 311 | BaseColor.link 312 | #endif 313 | } 314 | 315 | // MARK: iOS: System Colors 316 | /// A color that represents the system-provided blue color. 317 | public static var systemBlue: Color { 318 | #if os(iOS) || os(tvOS) 319 | Color(UIColor.systemBlue) 320 | #elseif os(macOS) 321 | Color(NSColor.systemBlue) 322 | #else 323 | BaseColor.systemGray2 324 | #endif 325 | } 326 | 327 | /// A color that represents the system-provided cyan color. 328 | public static var systemCyan: Color { 329 | #if os(iOS) || os(tvOS) 330 | if #available(iOS 15.0, tvOS 15.0, *) { 331 | Color(UIColor.systemCyan) 332 | } else { 333 | BaseColor.systemCyan 334 | } 335 | #elseif os(macOS) 336 | if #available(macOS 12.0, *) { 337 | Color(NSColor.systemCyan) 338 | } else { 339 | BaseColor.systemCyan 340 | } 341 | #else 342 | BaseColor.systemCyan 343 | #endif 344 | } 345 | 346 | /// A color that represents the system-provided mint color. 347 | public static var systemMint: Color { 348 | #if os(iOS) || os(tvOS) 349 | if #available(iOS 15.0, tvOS 15.0, *) { 350 | Color(UIColor.systemMint) 351 | } else { 352 | BaseColor.systemMint 353 | } 354 | #elseif os(macOS) 355 | if #available(macOS 10.12, *) { 356 | Color(NSColor.systemMint) 357 | } else { 358 | BaseColor.systemMint 359 | } 360 | #else 361 | BaseColor.systemMint 362 | #endif 363 | } 364 | 365 | /// A color that represents the system-provided purple color. 366 | public static var systemPurple: Color { 367 | #if os(iOS) || os(tvOS) 368 | Color(UIColor.systemPurple) 369 | #elseif os(macOS) 370 | Color(NSColor.systemPurple) 371 | #else 372 | BaseColor.systemPurple 373 | #endif 374 | } 375 | 376 | /// A color that represents the system-provided green color. 377 | public static var systemGreen: Color { 378 | #if os(iOS) || os(tvOS) 379 | Color(UIColor.systemGreen) 380 | #elseif os(macOS) 381 | Color(NSColor.systemGreen) 382 | #else 383 | BaseColor.systemGreen 384 | #endif 385 | } 386 | 387 | /// A color that represents the system-provided yellow color. 388 | public static var systemYellow: Color { 389 | #if os(iOS) || os(tvOS) 390 | Color(UIColor.systemYellow) 391 | #elseif os(macOS) 392 | Color(NSColor.systemYellow) 393 | #else 394 | BaseColor.systemYellow 395 | #endif 396 | } 397 | 398 | /// A color that represents the system-provided orange color. 399 | public static var systemOrange: Color { 400 | #if os(iOS) || os(tvOS) 401 | Color(UIColor.systemOrange) 402 | #elseif os(macOS) 403 | Color(NSColor.systemOrange) 404 | #else 405 | BaseColor.systemOrange 406 | #endif 407 | } 408 | 409 | /// A color that represents the system-provided pink color. 410 | public static var systemPink: Color { 411 | #if os(iOS) || os(tvOS) 412 | Color(UIColor.systemPink) 413 | #elseif os(macOS) 414 | Color(NSColor.systemPink) 415 | #else 416 | BaseColor.systemPink 417 | #endif 418 | } 419 | 420 | /// A color that represents the system-provided red color. 421 | public static var systemRed: Color { 422 | #if os(iOS) || os(tvOS) 423 | Color(UIColor.systemRed) 424 | #elseif os(macOS) 425 | Color(NSColor.systemRed) 426 | #else 427 | BaseColor.systemRed 428 | #endif 429 | } 430 | 431 | /// A color that represents the system-provided teal color. 432 | public static var systemTeal: Color { 433 | #if os(iOS) || os(tvOS) 434 | Color(UIColor.systemTeal) 435 | #elseif os(macOS) 436 | Color(NSColor.systemTeal) 437 | #else 438 | BaseColor.systemTeal 439 | #endif 440 | } 441 | 442 | /// A color that represents the system-provided indigo color. 443 | public static var systemIndigo: Color { 444 | #if os(iOS) || os(tvOS) 445 | Color(UIColor.systemIndigo) 446 | #elseif os(macOS) 447 | Color(NSColor.systemIndigo) 448 | #else 449 | BaseColor.systemIndigo 450 | #endif 451 | } 452 | 453 | // MARK: iOS: MacOS Specific 454 | /// A color that represents the system-provided scrubber textured background color. 455 | /// 456 | /// Use this color for the background of a scrubber control. 457 | public static var scrubberTexturedBackground: Color { 458 | #if os(macOS) 459 | Color(NSColor.scrubberTexturedBackground) 460 | #else 461 | BaseColor.scrubberTexturedBackground 462 | #endif 463 | } 464 | 465 | /// A color that represents the system-provided text background color. 466 | /// 467 | /// Use this color for the background of large text, such as in a text view or word processing document. 468 | public static var textBackgroundColor: Color { 469 | #if os(macOS) 470 | Color(NSColor.textBackgroundColor) 471 | #else 472 | BaseColor.textBackgroundColor 473 | #endif 474 | } 475 | 476 | /// A color that represents the system-provided control text color. 477 | /// 478 | /// Use this color for text on top of standard system controls. 479 | public static var controlTextColor: Color { 480 | #if os(macOS) 481 | Color(NSColor.controlTextColor) 482 | #else 483 | BaseColor.controlTextColor 484 | #endif 485 | } 486 | 487 | /// A color that represents the system-provided quaternary label color. 488 | /// 489 | /// Use this color for text labels that contain quaternary content. 490 | public static var quaternaryLabelColor: Color { 491 | #if os(macOS) 492 | Color(NSColor.quaternaryLabelColor) 493 | #else 494 | BaseColor.quaternaryLabelColor 495 | #endif 496 | } 497 | 498 | /// A color that represents the system-provided find highlight color. 499 | /// 500 | /// Use this color for the highlight color of find indicators. 501 | public static var findHighlightColor: Color { 502 | #if os(macOS) 503 | Color(NSColor.findHighlightColor) 504 | #else 505 | BaseColor.findHighlightColor 506 | #endif 507 | } 508 | 509 | /// A color that represents the system-provided highlight color. 510 | /// 511 | /// Use this color for the highlight color of selection controls. 512 | public static var highlightColor: Color { 513 | #if os(macOS) 514 | Color(NSColor.highlightColor) 515 | #else 516 | BaseColor.highlightColor 517 | #endif 518 | } 519 | /// A color that represents the system-provided shadow color. 520 | /// 521 | /// Use this color for shadows cast by raised objects on a surface. 522 | public static var shadowColor: Color { 523 | #if os(macOS) 524 | Color(NSColor.shadowColor) 525 | #else 526 | BaseColor.shadowColor 527 | #endif 528 | } 529 | 530 | /// A color that represents the system-provided window frame text color. 531 | /// 532 | /// Use this color for text in the frame of a window. 533 | public static var windowFrameTextColor: Color { 534 | #if os(macOS) 535 | Color(NSColor.windowFrameTextColor) 536 | #else 537 | BaseColor.windowFrameTextColor 538 | #endif 539 | } 540 | 541 | /// A color that represents the system-provided window background color. 542 | /// 543 | /// Use this color for the background of windows. 544 | public static var windowBackgroundColor: Color { 545 | #if os(macOS) 546 | Color(NSColor.windowBackgroundColor) 547 | #else 548 | BaseColor.windowBackgroundColor 549 | #endif 550 | } 551 | 552 | /// A color that represents the system-provided keyboard focus indicator color. 553 | /// 554 | /// Use this color for the keyboard focus ring around a control. 555 | public static var keyboardFocusIndicatorColor: Color { 556 | #if os(macOS) 557 | Color(NSColor.keyboardFocusIndicatorColor) 558 | #else 559 | BaseColor.keyboardFocusIndicatorColor 560 | #endif 561 | } 562 | 563 | /// A color that represents the system-provided separator color. 564 | /// 565 | /// Use this color for thin borders or divider lines that allows some underlying content to be visible. 566 | public static var separatorColor: Color { 567 | #if os(macOS) 568 | Color(NSColor.separatorColor) 569 | #else 570 | BaseColor.separatorColor 571 | #endif 572 | } 573 | 574 | /// A color that represents the system-provided selected control color. 575 | /// 576 | /// Use this color for the background of selected controls. 577 | public static var selectedControlColor: Color { 578 | #if os(macOS) 579 | Color(NSColor.selectedControlColor) 580 | #else 581 | BaseColor.selectedControlColor 582 | #endif 583 | } 584 | 585 | /// A color that represents the system-provided control background color. 586 | /// 587 | /// Use this color for the background of standard system controls. 588 | public static var controlBackgroundColor: Color { 589 | #if os(macOS) 590 | Color(NSColor.controlBackgroundColor) 591 | #else 592 | BaseColor.controlBackgroundColor 593 | #endif 594 | } 595 | 596 | /// A color that represents the system-provided secondary label color. 597 | /// 598 | /// Use this color for text labels that contain secondary content. 599 | public static var secondaryLabelColor: Color { 600 | #if os(macOS) 601 | Color(NSColor.secondaryLabelColor) 602 | #else 603 | BaseColor.secondaryLabelColor 604 | #endif 605 | } 606 | 607 | /// A color that represents the system-provided tertiary label color. 608 | /// 609 | /// Use this color for text labels that contain tertiary content. 610 | public static var tertiaryLabelColor: Color { 611 | #if os(macOS) 612 | Color(NSColor.tertiaryLabelColor) 613 | #else 614 | BaseColor.tertiaryLabelColor 615 | #endif 616 | } 617 | 618 | /// A color that represents the system-provided grid color. 619 | /// 620 | /// Use this color for gridlines in a table view. 621 | public static var gridColor: Color { 622 | #if os(macOS) 623 | Color(NSColor.gridColor) 624 | #else 625 | BaseColor.gridColor 626 | #endif 627 | } 628 | 629 | /// A color that represents the system-provided alternate selected control text color. 630 | /// 631 | /// Use this color for text on top of selected controls. 632 | public static var alternateSelectedControlTextColor: Color { 633 | #if os(macOS) 634 | Color(NSColor.alternateSelectedControlTextColor) 635 | #else 636 | BaseColor.alternateSelectedControlTextColor 637 | #endif 638 | } 639 | 640 | /// A color that represents the system-provided unemphasized selected content background color. 641 | /// 642 | /// Use this color for the background of selected content that is unemphasized. 643 | public static var unemphasizedSelectedContentBackgroundColor: Color { 644 | // swiftlint:disable:previous identifier_name 645 | #if os(macOS) 646 | Color(NSColor.unemphasizedSelectedContentBackgroundColor) 647 | #else 648 | BaseColor.unemphasizedSelectedContentBackgroundColor 649 | #endif 650 | } 651 | 652 | /// A color that represents the system-provided text color. 653 | /// 654 | /// Use this color for text labels. 655 | public static var textColor: Color { 656 | #if os(macOS) 657 | Color(NSColor.textColor) 658 | #else 659 | BaseColor.textColor 660 | #endif 661 | } 662 | 663 | /// A color that represents the system-provided system brown color. 664 | public static var systemBrown: Color { 665 | #if os(macOS) 666 | Color(NSColor.systemBrown) 667 | #else 668 | BaseColor.systemBrown 669 | #endif 670 | } 671 | 672 | /// A color that represents the system-provided selected content background color. 673 | /// 674 | /// Use this color for the background of selected content. 675 | public static var selectedContentBackgroundColor: Color { 676 | #if os(macOS) 677 | Color(NSColor.selectedContentBackgroundColor) 678 | #else 679 | BaseColor.selectedContentBackgroundColor 680 | #endif 681 | } 682 | 683 | /// A color that represents the system-provided selected text color. 684 | /// 685 | /// Use this color for selected text. 686 | public static var selectedTextColor: Color { 687 | #if os(macOS) 688 | Color(NSColor.selectedTextColor) 689 | #else 690 | BaseColor.selectedTextColor 691 | #endif 692 | } 693 | 694 | /// A color that represents the system-provided label color. 695 | /// 696 | /// Use this color for standard text labels. 697 | public static var labelColor: Color { 698 | #if os(macOS) 699 | Color(NSColor.labelColor) 700 | #else 701 | BaseColor.labelColor 702 | #endif 703 | } 704 | 705 | /// A color that represents the system-provided unemphasized selected text color. 706 | /// 707 | /// Use this color for unemphasized selected text. 708 | public static var placeholderTextColor: Color { 709 | #if os(macOS) 710 | Color(NSColor.placeholderTextColor) 711 | #else 712 | BaseColor.placeholderTextColor 713 | #endif 714 | } 715 | 716 | /// A color that represents the system-provided unemphasized selected text background color. 717 | /// 718 | /// Use this color for the background of unemphasized selected text. 719 | public static var unemphasizedSelectedTextBackgroundColor: Color { 720 | #if os(macOS) 721 | Color(NSColor.unemphasizedSelectedTextBackgroundColor) 722 | #else 723 | BaseColor.unemphasizedSelectedTextBackgroundColor 724 | #endif 725 | } 726 | 727 | /// A color that represents the system-provided disabled control text color. 728 | /// 729 | /// Use this color for text on disabled controls. 730 | public static var disabledControlTextColor: Color { 731 | #if os(macOS) 732 | Color(NSColor.disabledControlTextColor) 733 | #else 734 | BaseColor.disabledControlTextColor 735 | #endif 736 | } 737 | 738 | /// A color that represents the system-provided header text color. 739 | /// 740 | /// Use this color for text in headers. 741 | public static var headerTextColor: Color { 742 | #if os(macOS) 743 | Color(NSColor.headerTextColor) 744 | #else 745 | BaseColor.headerTextColor 746 | #endif 747 | } 748 | 749 | /// A color that represents the system-provided link color. 750 | /// 751 | /// Use this color for links. 752 | public static var linkColor: Color { 753 | #if os(macOS) 754 | Color(NSColor.linkColor) 755 | #else 756 | BaseColor.linkColor 757 | #endif 758 | } 759 | 760 | /// A color that represents the system-provided selected text background color. 761 | /// 762 | /// Use this color for the background of selected text. 763 | public static var selectedTextBackgroundColor: Color { 764 | #if os(macOS) 765 | Color(NSColor.selectedTextBackgroundColor) 766 | #else 767 | BaseColor.selectedTextBackgroundColor 768 | #endif 769 | } 770 | 771 | /// A color that represents the system-provided control color. 772 | /// 773 | /// Use this color for standard system controls. 774 | public static var unemphasizedSelectedTextColor: Color { 775 | #if os(macOS) 776 | Color(NSColor.unemphasizedSelectedTextColor) 777 | #else 778 | BaseColor.unemphasizedSelectedTextColor 779 | #endif 780 | } 781 | 782 | /// A color that represents the system-provided under page background color. 783 | /// 784 | /// Use this color for the background of a page that is under another page. 785 | public static var controlColor: Color { 786 | #if os(macOS) 787 | Color(NSColor.controlColor) 788 | #else 789 | BaseColor.controlColor 790 | #endif 791 | } 792 | 793 | /// A color that represents the system-provided selected control text color. 794 | /// 795 | /// Use this color for text on top of selected controls. 796 | public static var selectedControlTextColor: Color { 797 | #if os(macOS) 798 | Color(NSColor.selectedControlTextColor) 799 | #else 800 | BaseColor.selectedControlTextColor 801 | #endif 802 | } 803 | 804 | /// A color that represents the system-provided under page background color. 805 | /// 806 | /// Use this color for the background of a page that is under another page. 807 | public static var underPageBackgroundColor: Color { 808 | #if os(macOS) 809 | Color(NSColor.underPageBackgroundColor) 810 | #else 811 | BaseColor.underPageBackgroundColor 812 | #endif 813 | } 814 | 815 | /// A color that represents the system-provided selected menu item text color. 816 | /// 817 | /// Use this color for the text of selected menu items. 818 | public static var selectedMenuItemTextColor: Color { 819 | #if os(macOS) 820 | Color(NSColor.selectedMenuItemTextColor) 821 | #else 822 | BaseColor.selectedMenuItemTextColor 823 | #endif 824 | } 825 | } 826 | #endif 827 | 828 | // swiftlint:disable:this file_length 829 | -------------------------------------------------------------------------------- /Sources/Colors/BaseColors.swift: -------------------------------------------------------------------------------- 1 | // 2 | // Colors.swift 3 | // Colors 4 | // 5 | // Created by Wesley de Groot on 2024-08-22. 6 | // https://wesleydegroot.nl 7 | // 8 | // https://github.com/0xWDG/SwiftUI-Color 9 | // MIT License 10 | // 11 | 12 | #if canImport(SwiftUI) 13 | import SwiftUI 14 | 15 | /// A set of system-provided colors that adapt to the current environment. 16 | /// 17 | /// Use these colors to create visual continuity between your app and the system. 18 | /// These colors automatically adapt to vibrancy and accessibility settings, so they always remain readable. 19 | struct BaseColor { 20 | // swiftlint:disable:previous type_body_length 21 | /// A color that represents the system-provided text color. 22 | /// 23 | /// Use this color for text in a standard state, such as a label in a navigation bar or a system button. 24 | /// 25 | /// - Note: When possible, we recommend using `labelColor` and its variants, instead. 26 | public static let lightText = Color.dynamicColor( 27 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 28 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 29 | ) 30 | 31 | /// A color that represents the system-provided text color. 32 | /// 33 | /// Use this color for text in a standard state, such as a label in a navigation bar or a system button. 34 | /// 35 | /// - Note: When possible, we recommend using `labelColor` and its variants, instead. 36 | public static let darkText = Color.dynamicColor( 37 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 38 | dark: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1) 39 | ) 40 | 41 | /// Foreground color for placeholder text in controls or text fields or text views. 42 | /// 43 | /// Use this color for placeholder text in controls or text views. 44 | public static let placeholderText = Color.dynamicColor( 45 | light: .init(red: 0.24, green: 0.24, blue: 0.26, alpha: 1), 46 | dark: .init(red: 0.92, green: 0.92, blue: 0.96, alpha: 1) 47 | ) 48 | 49 | // MARK: - MacOS: Label Colors 50 | /// A color that represents the system-provided label color. 51 | /// 52 | /// Use this color for standard text labels. 53 | public static let label = Color.dynamicColor( 54 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 55 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 56 | ) 57 | 58 | /// A color that represents the system-provided secondary label color. 59 | /// 60 | /// Use this color for text labels that contain secondary content. 61 | public static let secondaryLabel = Color.dynamicColor( 62 | light: .init(red: 0.24, green: 0.24, blue: 0.26, alpha: 1), 63 | dark: .init(red: 0.92, green: 0.92, blue: 0.96, alpha: 1) 64 | ) 65 | 66 | /// A color that represents the system-provided tertiary label color. 67 | /// 68 | /// Use this color for text labels that contain tertiary content. 69 | public static let tertiaryLabel = Color.dynamicColor( 70 | light: .init(red: 0.24, green: 0.24, blue: 0.26, alpha: 1), 71 | dark: .init(red: 0.92, green: 0.92, blue: 0.96, alpha: 1) 72 | ) 73 | 74 | /// A color that represents the system-provided quaternary label color. 75 | /// 76 | /// Use this color for text labels that contain quaternary content. 77 | public static let quaternaryLabel = Color.dynamicColor( 78 | light: .init(red: 0.24, green: 0.24, blue: 0.26, alpha: 1), 79 | dark: .init(red: 0.92, green: 0.92, blue: 0.96, alpha: 1) 80 | ) 81 | 82 | // MARK: - MacOS: Background Colors 83 | /// A color that represents the system-provided background color. 84 | /// 85 | /// Use this color for the main background of your interface. 86 | public static let systemBackground = Color.dynamicColor( 87 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 88 | dark: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1) 89 | ) 90 | 91 | /// A color that represents the system-provided secondary background color. 92 | /// 93 | /// Use this color for content layered on top of the main background. 94 | public static let secondarySystemBackground = Color.dynamicColor( 95 | light: .init(red: 0.95, green: 0.95, blue: 0.97, alpha: 1), 96 | dark: .init(red: 0.11, green: 0.11, blue: 0.12, alpha: 1) 97 | ) 98 | 99 | /// A color that represents the system-provided tertiary background color. 100 | /// 101 | /// Use this color for content layered on top of secondary backgrounds. 102 | public static let tertiarySystemBackground = Color.dynamicColor( 103 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 104 | dark: .init(red: 0.17, green: 0.17, blue: 0.18, alpha: 1) 105 | ) 106 | 107 | // MARK: - MacOS: Fill Colors 108 | /// systemFillColor is appropriate for filling thin and small shapes. 109 | /// 110 | /// Example: The track of a slider. 111 | public static let systemFill = Color.dynamicColor( 112 | light: .init(red: 0.47, green: 0.47, blue: 0.50, alpha: 1), 113 | dark: .init(red: 0.47, green: 0.47, blue: 0.50, alpha: 1) 114 | ) 115 | /// secondarySystemFillColor is appropriate for filling medium-size shapes. 116 | /// 117 | /// Example: The background of a switch. 118 | public static let secondarySystemFill = Color.dynamicColor( 119 | light: .init(red: 0.47, green: 0.47, blue: 0.50, alpha: 1), 120 | dark: .init(red: 0.47, green: 0.47, blue: 0.50, alpha: 1) 121 | ) 122 | /// tertiarySystemFillColor is appropriate for filling large shapes. 123 | /// 124 | /// Examples: Input fields, search bars, buttons. 125 | public static let tertiarySystemFill = Color.dynamicColor( 126 | light: .init(red: 0.46, green: 0.46, blue: 0.50, alpha: 1), 127 | dark: .init(red: 0.46, green: 0.46, blue: 0.50, alpha: 1) 128 | ) 129 | /// quaternarySystemFillColor is appropriate for filling large areas containing complex content. 130 | /// 131 | /// Example: Expanded table cells. 132 | public static let quaternarySystemFill = Color.dynamicColor( 133 | light: .init(red: 0.45, green: 0.45, blue: 0.50, alpha: 1), 134 | dark: .init(red: 0.46, green: 0.46, blue: 0.50, alpha: 1) 135 | ) 136 | 137 | // MARK: - MacOS: Grouped Background Colors 138 | /// A color that represents the system-provided grouped background color. 139 | /// 140 | /// Use this color for the main background in a grouped interface, such as a grouped table view. 141 | public static let systemGroupedBackground = Color.dynamicColor( 142 | light: .init(red: 0.95, green: 0.95, blue: 0.97, alpha: 1), 143 | dark: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1) 144 | ) 145 | 146 | /// A color that represents the system-provided secondary grouped background color. 147 | /// 148 | /// Use this color for content layered on top of the main grouped background. 149 | public static let secondarySystemGroupedBackground = Color.dynamicColor( 150 | light: .init(red: 0.11, green: 0.11, blue: 0.12, alpha: 1), 151 | dark: .init(red: 1, green: 1, blue: 1, alpha: 1) 152 | ) 153 | 154 | /// A color that represents the system-provided tertiary grouped background color. 155 | /// 156 | /// Use this color for content layered on top of secondary grouped backgrounds. 157 | public static let tertiarySystemGroupedBackground = Color.dynamicColor( 158 | light: .init(red: 0.95, green: 0.95, blue: 0.97, alpha: 1), 159 | dark: .init(red: 0.17, green: 0.17, blue: 0.18, alpha: 1) 160 | ) 161 | 162 | // MARK: - MacOS: Gray Colors 163 | /// A color that represents the system-provided gray color. 164 | /// 165 | /// Use this color for standard text labels. 166 | public static let systemGray = Color.dynamicColor( 167 | light: .init(red: 0.56, green: 0.56, blue: 0.58, alpha: 1), 168 | dark: .init(red: 0.56, green: 0.56, blue: 0.58, alpha: 1) 169 | ) 170 | 171 | /// A color that represents the system-provided gray2 color. 172 | /// 173 | /// Use this color for text labels that contain secondary content. 174 | public static let systemGray2 = Color.dynamicColor( 175 | light: .init(red: 0.68, green: 0.68, blue: 0.70, alpha: 1), 176 | dark: .init(red: 0.39, green: 0.39, blue: 0.40, alpha: 1) 177 | ) 178 | 179 | /// A color that represents the system-provided gray3 color. 180 | /// 181 | /// Use this color for text labels that contain tertiary content. 182 | public static let systemGray3 = Color.dynamicColor( 183 | light: .init(red: 0.78, green: 0.78, blue: 0.80, alpha: 1), 184 | dark: .init(red: 0.28, green: 0.28, blue: 0.29, alpha: 1) 185 | ) 186 | 187 | /// A color that represents the system-provided gray4 color. 188 | /// 189 | /// Use this color for text labels that contain quaternary content. 190 | public static let systemGray4 = Color.dynamicColor( 191 | light: .init(red: 0.82, green: 0.82, blue: 0.84, alpha: 1), 192 | dark: .init(red: 0.23, green: 0.23, blue: 0.24, alpha: 1) 193 | ) 194 | 195 | /// A color that represents the system-provided gray5 color. 196 | /// 197 | /// Use this color for text labels that contain quinary content. 198 | public static let systemGray5 = Color.dynamicColor( 199 | light: .init(red: 0.90, green: 0.90, blue: 0.92, alpha: 1), 200 | dark: .init(red: 0.17, green: 0.17, blue: 0.18, alpha: 1) 201 | ) 202 | 203 | /// A color that represents the system-provided gray6 color. 204 | /// 205 | /// Use this color for text labels that contain senary content. 206 | public static let systemGray6 = Color.dynamicColor( 207 | light: .init(red: 0.95, green: 0.95, blue: 0.97, alpha: 1), 208 | dark: .init(red: 0.11, green: 0.11, blue: 0.12, alpha: 1) 209 | ) 210 | 211 | // MARK: - MacOS: Other Colors 212 | /// A color that represents the system-provided separator color. 213 | /// 214 | /// Use this color for thin borders or divider lines that allows some underlying content to be visible. 215 | public static let separator = Color.dynamicColor( 216 | light: .init(red: 0.24, green: 0.24, blue: 0.26, alpha: 1), 217 | dark: .init(red: 0.33, green: 0.33, blue: 0.35, alpha: 1) 218 | ) 219 | 220 | /// A color that represents the system-provided opaque separator color. 221 | /// 222 | /// Use this color for borders or divider lines that are opaque. 223 | public static let opaqueSeparator = Color.dynamicColor( 224 | light: .init(red: 0.78, green: 0.78, blue: 0.78, alpha: 1), 225 | dark: .init(red: 0.22, green: 0.22, blue: 0.23, alpha: 1) 226 | ) 227 | 228 | /// A color that represents the system-provided link color. 229 | /// 230 | /// Use this color for links. 231 | public static let link = Color.dynamicColor( 232 | light: .init(red: 0.00, green: 0.48, blue: 1.00, alpha: 1), 233 | dark: .init(red: 0.04, green: 0.52, blue: 1.00, alpha: 1) 234 | ) 235 | 236 | // MARK: MacOS: System Colors 237 | /// A color that represents the system-provided blue color. 238 | public static let systemBlue = Color.dynamicColor( 239 | light: .init(red: 0.00, green: 0.48, blue: 1.00, alpha: 1), 240 | dark: .init(red: 0.04, green: 0.52, blue: 1.00, alpha: 1) 241 | ) 242 | 243 | /// A color that represents the system-provided cyan color. 244 | public static let systemCyan = Color.dynamicColor( 245 | light: .init(red: 0.20, green: 0.68, blue: 0.90, alpha: 1), 246 | dark: .init(red: 0.39, green: 0.82, blue: 1.00, alpha: 1) 247 | ) 248 | 249 | /// A color that represents the system-provided mint color. 250 | public static let systemMint = Color.dynamicColor( 251 | light: .init(red: 0.00, green: 0.78, blue: 0.74, alpha: 1), 252 | dark: .init(red: 0.39, green: 0.90, blue: 0.89, alpha: 1) 253 | ) 254 | 255 | /// A color that represents the system-provided purple color. 256 | public static let systemPurple = Color.dynamicColor( 257 | light: .init(red: 0.69, green: 0.32, blue: 0.87, alpha: 1), 258 | dark: .init(red: 0.75, green: 0.35, blue: 0.95, alpha: 1) 259 | ) 260 | 261 | /// A color that represents the system-provided green color. 262 | public static let systemGreen = Color.dynamicColor( 263 | light: .init(red: 0.20, green: 0.78, blue: 0.35, alpha: 1), 264 | dark: .init(red: 0.19, green: 0.82, blue: 0.35, alpha: 1) 265 | ) 266 | 267 | /// A color that represents the system-provided yellow color. 268 | public static let systemYellow = Color.dynamicColor( 269 | light: .init(red: 1.00, green: 0.80, blue: 0.00, alpha: 1), 270 | dark: .init(red: 1.00, green: 0.84, blue: 0.04, alpha: 1) 271 | ) 272 | 273 | /// A color that represents the system-provided orange color. 274 | public static let systemOrange = Color.dynamicColor( 275 | light: .init(red: 1.00, green: 0.58, blue: 0.00, alpha: 1), 276 | dark: .init(red: 1.00, green: 0.62, blue: 0.04, alpha: 1) 277 | ) 278 | 279 | /// A color that represents the system-provided pink color. 280 | public static let systemPink = Color.dynamicColor( 281 | light: .init(red: 1.00, green: 0.18, blue: 0.33, alpha: 1), 282 | dark: .init(red: 1.00, green: 0.22, blue: 0.37, alpha: 1) 283 | ) 284 | 285 | /// A color that represents the system-provided red color. 286 | public static let systemRed = Color.dynamicColor( 287 | light: .init(red: 1.00, green: 0.23, blue: 0.19, alpha: 1), 288 | dark: .init(red: 1.00, green: 0.27, blue: 0.23, alpha: 1) 289 | ) 290 | 291 | /// A color that represents the system-provided teal color. 292 | public static let systemTeal = Color.dynamicColor( 293 | light: .init(red: 0.35, green: 0.78, blue: 0.98, alpha: 1), 294 | dark: .init(red: 0.39, green: 0.82, blue: 1.00, alpha: 1) 295 | ) 296 | 297 | /// A color that represents the system-provided indigo color. 298 | public static let systemIndigo = Color.dynamicColor( 299 | light: .init(red: 0.35, green: 0.34, blue: 0.84, alpha: 1), 300 | dark: .init(red: 0.37, green: 0.36, blue: 0.90, alpha: 1) 301 | ) 302 | 303 | /// A color that represents the system-provided scrubber textured background color. 304 | /// 305 | /// Use this color for the background of a scrubber control. 306 | public static let scrubberTexturedBackground = Color.dynamicColor( 307 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 308 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 309 | ) 310 | 311 | /// A color that represents the system-provided text background color. 312 | /// 313 | /// Use this color for the background of large text, such as in a text view or word processing document. 314 | public static let textBackgroundColor = Color.dynamicColor( 315 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 316 | dark: .init(red: 0.12, green: 0.12, blue: 0.12, alpha: 1) 317 | ) 318 | 319 | /// A color that represents the system-provided control text color. 320 | /// 321 | /// Use this color for text on top of standard system controls. 322 | public static let controlTextColor = Color.dynamicColor( 323 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 324 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 325 | ) 326 | 327 | /// A color that represents the system-provided quaternary label color. 328 | /// 329 | /// Use this color for text labels that contain quaternary content. 330 | public static let quaternaryLabelColor = Color.dynamicColor( 331 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 332 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 333 | ) 334 | 335 | /// A color that represents the system-provided find highlight color. 336 | /// 337 | /// Use this color for the highlight color of find indicators. 338 | public static let findHighlightColor = Color.dynamicColor( 339 | light: .init(red: 1.00, green: 1.00, blue: 0.00, alpha: 1), 340 | dark: .init(red: 1.00, green: 1.00, blue: 0.00, alpha: 1) 341 | ) 342 | 343 | /// A color that represents the system-provided highlight color. 344 | /// 345 | /// Use this color for the highlight color of selection controls. 346 | public static let highlightColor = Color.dynamicColor( 347 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 348 | dark: .init(red: 0.71, green: 0.71, blue: 0.71, alpha: 1) 349 | ) 350 | 351 | /// A color that represents the system-provided shadow color. 352 | /// 353 | /// Use this color for shadows cast by raised objects on a surface. 354 | public static let shadowColor = Color.dynamicColor( 355 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 356 | dark: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1) 357 | ) 358 | 359 | /// A color that represents the system-provided window frame text color. 360 | /// 361 | /// Use this color for text in the frame of a window. 362 | public static let windowFrameTextColor = Color.dynamicColor( 363 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 364 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 365 | ) 366 | 367 | /// A color that represents the system-provided window background color. 368 | /// 369 | /// Use this color for the background of windows. 370 | public static let windowBackgroundColor = Color.dynamicColor( 371 | light: .init(red: 0.93, green: 0.93, blue: 0.93, alpha: 1), 372 | dark: .init(red: 0.20, green: 0.20, blue: 0.20, alpha: 1) 373 | ) 374 | 375 | /// A color that represents the system-provided keyboard focus indicator color. 376 | /// 377 | /// Use this color for the keyboard focus ring around a control. 378 | public static let keyboardFocusIndicatorColor = Color.dynamicColor( 379 | light: .init(red: 0.00, green: 0.40, blue: 0.96, alpha: 1), 380 | dark: .init(red: 0.10, green: 0.66, blue: 1.00, alpha: 1) 381 | ) 382 | 383 | /// A color that represents the system-provided separator color. 384 | /// 385 | /// Use this color for thin borders or divider lines that allows some underlying content to be visible. 386 | public static let separatorColor = Color.dynamicColor( 387 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 388 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 389 | ) 390 | 391 | /// A color that represents the system-provided selected control color. 392 | /// 393 | /// Use this color for the background of selected controls. 394 | public static let selectedControlColor = Color.dynamicColor( 395 | light: .init(red: 0.70, green: 0.84, blue: 1.00, alpha: 1), 396 | dark: .init(red: 0.25, green: 0.39, blue: 0.55, alpha: 1) 397 | ) 398 | 399 | /// A color that represents the system-provided control background color. 400 | /// 401 | /// Use this color for the background of standard system controls. 402 | public static let controlBackgroundColor = Color.dynamicColor( 403 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 404 | dark: .init(red: 0.12, green: 0.12, blue: 0.12, alpha: 1) 405 | ) 406 | 407 | /// A color that represents the system-provided secondary label color. 408 | /// 409 | /// Use this color for text labels that contain secondary content. 410 | public static let secondaryLabelColor = Color.dynamicColor( 411 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 412 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 413 | ) 414 | 415 | /// A color that represents the system-provided tertiary label color. 416 | /// 417 | /// Use this color for text labels that contain tertiary content. 418 | public static let tertiaryLabelColor = Color.dynamicColor( 419 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 420 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 421 | ) 422 | 423 | /// A color that represents the system-provided grid color. 424 | /// 425 | /// Use this color for gridlines in a table view. 426 | public static let gridColor = Color.dynamicColor( 427 | light: .init(red: 0.90, green: 0.90, blue: 0.90, alpha: 1), 428 | dark: .init(red: 0.10, green: 0.10, blue: 0.10, alpha: 1) 429 | ) 430 | 431 | /// A color that represents the system-provided alternate selected control text color. 432 | /// 433 | /// Use this color for text on top of selected controls. 434 | public static let alternateSelectedControlTextColor = Color.dynamicColor( 435 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 436 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 437 | ) 438 | 439 | /// A color that represents the system-provided unemphasized selected content background color. 440 | /// 441 | /// Use this color for the background of selected content that is unemphasized. 442 | public static let unemphasizedSelectedContentBackgroundColor = Color.dynamicColor( 443 | // swiftlint:disable:previous identifier_name 444 | light: .init(red: 0.86, green: 0.86, blue: 0.86, alpha: 1), 445 | dark: .init(red: 0.27, green: 0.27, blue: 0.27, alpha: 1) 446 | ) 447 | 448 | /// A color that represents the system-provided text color. 449 | /// 450 | /// Use this color for text labels. 451 | public static let textColor = Color.dynamicColor( 452 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 453 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 454 | ) 455 | 456 | /// A color that represents the system-provided system brown color. 457 | public static let systemBrown = Color.dynamicColor( 458 | light: .init(red: 0.64, green: 0.52, blue: 0.37, alpha: 1), 459 | dark: .init(red: 0.67, green: 0.56, blue: 0.41, alpha: 1) 460 | ) 461 | 462 | /// A color that represents the system-provided selected content background color. 463 | /// 464 | /// Use this color for the background of selected content. 465 | public static let selectedContentBackgroundColor = Color.dynamicColor( 466 | light: .init(red: 0.00, green: 0.39, blue: 0.88, alpha: 1), 467 | dark: .init(red: 0.00, green: 0.35, blue: 0.82, alpha: 1) 468 | ) 469 | 470 | /// A color that represents the system-provided selected text color. 471 | /// 472 | /// Use this color for selected text. 473 | public static let selectedTextColor = Color.dynamicColor( 474 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 475 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 476 | ) 477 | 478 | /// A color that represents the system-provided label color. 479 | /// 480 | /// Use this color for standard text labels. 481 | public static let labelColor = Color.dynamicColor( 482 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 483 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 484 | ) 485 | 486 | /// A color that represents the system-provided unemphasized selected text color. 487 | /// 488 | /// Use this color for unemphasized selected text. 489 | public static let placeholderTextColor = Color.dynamicColor( 490 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 491 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 492 | ) 493 | 494 | /// A color that represents the system-provided unemphasized selected text background color. 495 | /// 496 | /// Use this color for the background of unemphasized selected text. 497 | public static let unemphasizedSelectedTextBackgroundColor = Color.dynamicColor( 498 | light: .init(red: 0.86, green: 0.86, blue: 0.86, alpha: 1), 499 | dark: .init(red: 0.27, green: 0.27, blue: 0.27, alpha: 1) 500 | ) 501 | 502 | /// A color that represents the system-provided disabled control text color. 503 | /// 504 | /// Use this color for text on disabled controls. 505 | public static let disabledControlTextColor = Color.dynamicColor( 506 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 507 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 508 | ) 509 | 510 | /// A color that represents the system-provided header text color. 511 | /// 512 | /// Use this color for text in headers. 513 | public static let headerTextColor = Color.dynamicColor( 514 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 515 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 516 | ) 517 | 518 | /// A color that represents the system-provided link color. 519 | /// 520 | /// Use this color for links. 521 | public static let linkColor = Color.dynamicColor( 522 | light: .init(red: 0.00, green: 0.41, blue: 0.85, alpha: 1), 523 | dark: .init(red: 0.25, green: 0.61, blue: 1.00, alpha: 1) 524 | ) 525 | 526 | /// A color that represents the system-provided selected text background color. 527 | /// 528 | /// Use this color for the background of selected text. 529 | public static let selectedTextBackgroundColor = Color.dynamicColor( 530 | light: .init(red: 0.70, green: 0.84, blue: 1.00, alpha: 1), 531 | dark: .init(red: 0.25, green: 0.39, blue: 0.55, alpha: 1) 532 | ) 533 | 534 | /// A color that represents the system-provided control color. 535 | /// 536 | /// Use this color for standard system controls. 537 | public static let unemphasizedSelectedTextColor = Color.dynamicColor( 538 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 539 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 540 | ) 541 | 542 | /// A color that represents the system-provided under page background color. 543 | /// 544 | /// Use this color for the background of a page that is under another page. 545 | public static let controlColor = Color.dynamicColor( 546 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 547 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 548 | ) 549 | 550 | /// A color that represents the system-provided selected control text color. 551 | /// 552 | /// Use this color for text on top of selected controls. 553 | public static let selectedControlTextColor = Color.dynamicColor( 554 | light: .init(red: 0.00, green: 0.00, blue: 0.00, alpha: 1), 555 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 556 | ) 557 | 558 | /// A color that represents the system-provided under page background color. 559 | /// 560 | /// Use this color for the background of a page that is under another page. 561 | public static let underPageBackgroundColor = Color.dynamicColor( 562 | light: .init(red: 0.59, green: 0.59, blue: 0.59, alpha: 1), 563 | dark: .init(red: 0.16, green: 0.16, blue: 0.16, alpha: 1) 564 | ) 565 | 566 | /// A color that represents the system-provided selected menu item text color. 567 | /// 568 | /// Use this color for the text of selected menu items. 569 | public static let selectedMenuItemTextColor = Color.dynamicColor( 570 | light: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1), 571 | dark: .init(red: 1.00, green: 1.00, blue: 1.00, alpha: 1) 572 | ) 573 | } 574 | 575 | #endif 576 | 577 | #if canImport(AppKit) 578 | extension Color { 579 | static func dynamicColor(light: NSColor, dark: NSColor, named: String = "DynamicColor") -> Color { 580 | return Color( 581 | NSColor( 582 | name: named, 583 | dynamicProvider: { traits in 584 | if traits.name == .darkAqua || traits.name == .vibrantDark { 585 | return dark 586 | } else { 587 | return light 588 | } 589 | } 590 | ) 591 | ) 592 | } 593 | } 594 | #endif 595 | 596 | #if canImport(UIKit) 597 | extension Color { 598 | static func dynamicColor(light: UIColor, dark: UIColor, named: String = "DynamicColor") -> Color { 599 | #if os(watchOS) 600 | return Color(dark) 601 | #else 602 | return Color( 603 | UIColor( 604 | dynamicProvider: { trait in 605 | return trait.userInterfaceStyle == .dark ? dark : light 606 | } 607 | ) 608 | ) 609 | #endif 610 | } 611 | } 612 | #endif 613 | 614 | // swiftlint:disable:this file_length 615 | --------------------------------------------------------------------------------