{"id":15055410,"url":"https://github.com/dscyrescotti/swifttheming","last_synced_at":"2025-04-10T03:40:32.918Z","repository":{"id":38322100,"uuid":"423561617","full_name":"dscyrescotti/SwiftTheming","owner":"dscyrescotti","description":"A powerful lightweight theme manager for SwiftUI","archived":false,"fork":false,"pushed_at":"2023-06-28T15:58:49.000Z","size":36443,"stargazers_count":86,"open_issues_count":7,"forks_count":4,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T04:51:38.100Z","etag":null,"topics":["appearance","apple","color-scheme","ios","macos","swift","swiftpackagemanager","swiftui","theme"],"latest_commit_sha":null,"homepage":"https://dscyrescotti.github.io/SwiftTheming/documentation/swifttheming/","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dscyrescotti.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-11-01T17:47:07.000Z","updated_at":"2025-03-20T14:37:01.000Z","dependencies_parsed_at":"2022-08-09T03:00:36.926Z","dependency_job_id":"10991234-6d69-4b6b-8a00-fce7d30ea2eb","html_url":"https://github.com/dscyrescotti/SwiftTheming","commit_stats":{"total_commits":159,"total_committers":4,"mean_commits":39.75,"dds":0.3647798742138365,"last_synced_commit":"1042f7b3f3b56ad64f8187939f6fe2e24d809471"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dscyrescotti%2FSwiftTheming","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dscyrescotti%2FSwiftTheming/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dscyrescotti%2FSwiftTheming/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dscyrescotti%2FSwiftTheming/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dscyrescotti","download_url":"https://codeload.github.com/dscyrescotti/SwiftTheming/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248154742,"owners_count":21056541,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["appearance","apple","color-scheme","ios","macos","swift","swiftpackagemanager","swiftui","theme"],"created_at":"2024-09-24T21:41:52.688Z","updated_at":"2025-04-10T03:40:32.831Z","avatar_url":"https://github.com/dscyrescotti.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp  align=\"center\"\u003e\n\u003cimg  width=\"70%\" src=\"https://github.com/dscyrescotti/SwiftTheming/blob/main/Assets/swift-theming-logo.png?raw=true\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://swiftpackageindex.com/dscyrescotti/SwiftTheming\"\u003e\n\t    \u003cimg  src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdscyrescotti%2FSwiftTheming%2Fbadge%3Ftype%3Dplatforms\"/\u003e \n    \u003c/a\u003e\n    \u003ca href=\"https://swiftpackageindex.com/dscyrescotti/SwiftTheming\"\u003e\n\t    \u003cimg  src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fdscyrescotti%2FSwiftTheming%2Fbadge%3Ftype%3Dswift-versions\"/\u003e \n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/dscyrescotti/SwiftTheming\"\u003e\n\t    \u003cimg  src=\"https://codecov.io/gh/dscyrescotti/SwiftTheming/branch/main/graph/badge.svg?token=D7DRKAD0VP\"/\u003e \n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/dscyrescotti/SwiftTheming/actions/workflows/swift.yml\"\u003e\n     \t\u003cimg src=\"https://github.com/dscyrescotti/SwiftTheming/actions/workflows/swift.yml/badge.svg\" alt=\"Action Status\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"LICENSE\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/license-MIT-brightgreen.svg\" alt=\"MIT License\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n**SwiftTheming 🎨** is a handy light-weight handy theme manager which handles multiple themes based on system-wide appearances - light and dark appearances and overrides the system appearance for the application.\n\n## 📱 Demo\n\u003cimg src=\"https://github.com/dscyrescotti/SwiftTheming/blob/main/Assets/demo-app.gif?raw=true\" alt=\"this slowpoke moves\"  width=\"40%\"/\u003e\u003cbr/\u003e\n\u003e *You can see the demo project in **Example** folder.*\n\n## 🎉 Motivation \nImagine that you want to achieve injecting multiple themes and manage them depending on the current system appearance or your preferred appearance. As SwiftUI does not come with the mechanism to manage different themes, you have to come up with it on your own. To me, I want to focus on other time-consuming stuff and don't want to spend on it. So, the idea to implement the handy mechanism for developers came to me and I eventually started crafting it. That was the becoming of **SwiftTheming**. 🎉🎉🎉 Using **SwiftTheming**, we can manage theme and system appearance as you desire without too much sweating. All you have to do is declare your themes with different colors, images, fonts and gradients. Pretty easy!\n\n## ⚠️ Requirements \n- iOS 14+, macOS 11+, watchOS 7+, tvOS 14+\n\n\u003e ***SwiftTheming** is developed using Xcode 13.0. Make sure you are using Xcode 13 and above.*\n\n## 🛠 Installation \n### 📦 Using Swift Package Manager\nAdd it as a dependency within your `Package.swift`.\n```swift\ndependencies: [\n    .package(url: \"https://github.com/dscyrescotti/SwiftTheming.git\", from: \"2.0.0\")\n]\n```\n### 📦 Using Cocoapods\nAdd it inside your `Podfile`.\n```ruby\npod 'SwiftTheming', '~\u003e 2.0.0'\n```\n\u003e *Currently, SwiftTheming can be installed only via Swift Package Manager and Cocoapods.*\n\n## 👀 Migration guide for Version 2\n**SwiftTheming 🎨** has released Version 2 which inlcudes the major enhancement for code architecture and developer experience. Please check out the [migration guide](https://github.com/dscyrescotti/SwiftTheming/blob/main/MigrationGuide.md) to migrate from Version 1.\n\n## 🎯 Usage\n### Declaring multiple themes\nTo get started, you need to define four different types of assets for color, font, gradient and image. Later, they will be used when creating different themes by injecting them as type alias.\n```swift\nenum ColorAsset: ColorAssetable {\n    case backgroundColor\n    // more...\n}\nenum FontAsset: FontAssetable { /* more... */ }\nenum GradientAsset: GradientAssetable { /* more... */ }\nenum ImageAsset: ImageAssetable { /* more...}\n```\n\u003e You can omit some assets unless those are intended to use in themes.\n\nNow, we can start designating different themes using the assets declared.\n```swift\nclass SampleTheme: Themed, Assetable {\n    typealias _ColorAsset = ColorAsset\n    typealias _FontAsset = FontAsset\n    typealias _GradientAsset = GradientAsset\n    typealias _ImageAsset = ImageAsset\n\n    func colorSet(for asset: ColorAsset) -\u003e ColorSet {\n        switch asset {\n        case .backgroundColor:\n            return ColorSet(light: Color(hex: 0xDEF8EA), dark: Color(hex: 0x22442E))\n        }\n    }\n    func imageSet(for asset: ImageAsset) -\u003e ImageSet { /* some stuff*/ }\n    func fontSet(for asset: FontAsset) -\u003e FontSet { /* some stuff */ }\n    func gradientSet(for asset: GradientAsset) -\u003e GradientSet { /* some stuff */ }\n}\n```\n\u003e For empty asset, you can directly use `EmptyAsset` instead of declaring an asset.\n\u003e ```swift\n\u003e class SampleTheme: Themed, Assetable {\n\u003e   typealias _GradientAsset = EmptyAsset\n\u003e }\n\u003e ```\n\nAfter you create multiple themes, it is time to list down all themes in `Theme` extension that you are going to use in the app and provide the required specification for `Themeable` protocol.\n```swift\nextension Theme: Themeable {\n    static let sampleTheme = Theme(key: \"sampleTheme\")\n    // more themes\n    \n    public func themed() -\u003e Themed {\n        switch self{\n        case .sampleTheme: return SampleTheme()\n        // some stuff\n        default: fatalError(\"You are accessing undefined theme.\")\n        }\n    }\n}\n```\n\n### Declaring default theming\nBefore moving to the part that explains how to use theme providers and access interface elements in view layers, you need to set up the default theme and appearance for the first time running. You can achieve it by letting `DefaultTheming` conforms to `Defaultable` and providing desired theme and appearance which will be used as defaults.\n```swift\nextension DefaultTheming: Defaultable {\n    public func defaultTheme() -\u003e Theme {\n        .sampleTheme\n    }\n    \n    public func defaultAppearance() -\u003e PreferredAppearance {\n        .system\n    }\n}\n```\n\n### Accessing theme provider across views\nYay! you are ready to use themes in your views. Let's get started passing `ThemeProvider` instance living as an environment object across view hierarchy so that it can be accessible across views.\n```swift\nWindowGroup {\n    ContentView()\n        .themeProviding()\n}\n```\nNow, you can access `ThemeProvider` via `@ThemeProviding` property wrapper inside any view so that you can fully manage themes and override the system appearance as you want through `themeProvider`.\n```swift\nstruct ContentView: View {\n    @ThemeProviding var themeProvider\n    \n    var body: some View { /* some stuff */ }\n}\n```\nYou can switch theme and appearance by calling `setTheme(with:)` and `setPreferredAppearance(with:)`respectively.\n\n## 🔎 Exploration\nTo explore more about **SwiftTheming 🎨**, you can check out the [documentation](https://dscyrescotti.github.io/SwiftTheming/documentation/swifttheming/) or dig around the source code.\n\n## ✍️ Author\n**Scotti** (**[@dscyrescotti](https://twitter.com/dscyrescotti)**)\n\n## 👨‍💻 Contributions\n\n**SwiftTheming 🎨**  welcomes all developers to contribute if you have any idea to enhance and open an issue if you encounter any bug.\n\n## © License\n\n**SwiftTheming 🎨** is available under the MIT license. See the  [LICENSE](https://github.com/dscyrescotti/SwiftTheming/blob/main/LICENSE)  file for more info.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdscyrescotti%2Fswifttheming","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdscyrescotti%2Fswifttheming","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdscyrescotti%2Fswifttheming/lists"}