A powerful lightweight theme 🎨 manager for SwiftUI

Overview

Action Status MIT License

SwiftTheming 🎨 is a handy lightweight handy theme manager which handles multiple themes based on system-wide appearances - light and dark appearances and overrides the system appearance for the application.

Demo πŸ“±

this slowpoke moves

You can see the demo project in Example folder.

Motivation πŸŽ‰

Imagine that you want to achieve injecting multiple themes and managing 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!

Requirements ⚠️

  • iOS 14+, macOS 11+, watchOS 7+, tvOS 14+

SwiftTheming is developed using Xcode 13.0. Make sure you are using Xcode 13 and above.

Installation πŸ› 

Using Swift Package Manager πŸ“¦

Add it as a dependency within your Package.swift.

dependencies: [
    .package(url: "https://github.com/dscyrescotti/SwiftTheming.git", from: "1.0.0")
]

Currently, SwiftTheming can be installed only via Swift Package Manager.

Usage πŸ“‹

Defining multiple themes

To get started, you need to declare the abstraction layer of asset that may contain a group of colors, images, gradients and/or fonts. It will be injected into different themes that you create later.

struct Asset: Assetable {
    enum ColorAsset {
        case backgroundColor
        // more...
    }
    enum ImageAsset { // more... }
    enum FontAsset { // more... }
    enum GradientAsset { // more... }
}

Now, we can start designating different themes based on the above asset.

class SampleTheme: Themed<Asset> {
    override func colorSet(for asset: Asset.ColorAsset) -> ColorSet {
        switch asset {
        case .backgroundColor:
            return ColorSet(light: Color.red, dark: Color.pink)
        }
    }
    override func imageSet(for asset: Asset.ImageAsset) -> ImageSet { // some stuff... }
    override func fontSet(for asset: Asset.FontAsset) -> FontSet { // some stuff... }
    override func gradientSet(for asset: Asset.GradientAsset) -> GradientSet { // some stuff... }
}

Make sure you override the above methods before you call. If not , you will end up with fatal error.

After you create multiple themes, it is time to list down all themes that you are going to use in app.

enum Theme: Themeable {
    case sampleTheme
    // more...
    
    func theme() -> Themed<Asset> {
        switch self {
        case .sampleTheme: return SampleTheme()
        // more...
        }
    }
}

Accessing theme provider across views

Yay! you are ready to use themes in your views. Let's get started to pass ThemeProvider across view hierarchy. Here you can set default theme and default appearance for first time running.

WindowGroup {
    ContentView()
        .themeProviding(defaultTheme: Theme.sampleTheme, defaultAppearance: .system)
}

Now, you can access ThemeProvider via @ThemeProviding property wrapper inside any view so that you can easily use assets prepopulated by passing it.

struct ContentView: View {
    @ThemeProviding<Theme> var themeProvider
    
    var body: some View {
        Color(on: themeProvider, for: .backgroundColor)
    }
}

Switching theme and appearance

You can change theme and appearance by callingsetTheme(with:)and setPreferredAppearance(with:)respectively.

Author πŸ–‹

Dscyre Scotti (@dscyrescotti)

Contributions πŸ‘¨β€πŸ’» πŸ§‘β€πŸ’» πŸ‘©β€πŸ’»

SwiftTheming 🎨 welcomes all developers to contribute if you have any idea to enhance and open an issue if you encounter any bug.

License πŸ“ƒ

SwiftTheming 🎨 is available under the MIT license. See the LICENSE file for more info.

You might also like...
FlexibleImage is implemented with the hope that anyone could easily develop an app that provides features such as Camera Filter and Theme.
FlexibleImage is implemented with the hope that anyone could easily develop an app that provides features such as Camera Filter and Theme.

FlexibleImage is implemented with the hope that anyone could easily develop an app that provides features such as Camera Filter and Theme. When you wr

πŸ‘•πŸ‘š Theme management in Swift
πŸ‘•πŸ‘š Theme management in Swift

Themes Story Ever want to support Night mode? Or skin the app differently depending on the seasons? Or toggle features according to paid status? Well,

An unintrusive & light-weight iOS app-theming library with support for animated theme switching.
An unintrusive & light-weight iOS app-theming library with support for animated theme switching.

Gestalt Gestalt is an unintrusive and light-weight framework for application theming with support for animated theme switching. Usage Let's say you wa

A very simple soundboard that plays the first 5 seconds of the CSI Miami theme (YEAAAAAAAAAA)

MiamiSunglasses This app is a single-sound soundboard that plays the first few seconds of the CSI Miami theme song when you press the sunglasses. Disc

A Publish theme. ckitakishi.com is built with PaletteTheme
A Publish theme. ckitakishi.com is built with PaletteTheme

PaletteTheme A Publish theme. ckitakishi.com is built with PaletteTheme. Features Simple and fast Mobile friendly Support both Light/Dark mode Customi

This repository contains 🎨 My Xcode theme that I use. It is compatible with all versions of Xcode.
This repository contains 🎨 My Xcode theme that I use. It is compatible with all versions of Xcode.

DRL Xcodetheme Installation Automatic (via script) ./install.sh which will install the file in Xcode FontAndColorThemes directory. Restart Xcode Go t

Theme handling macOS Appkit (Swift/Objective-C)

DSFAppearanceManager A class for simplifying macOS appearance values and detecting setting changes (Swift/Objective-C). Why? If you're performing cust

Solarized Dark Theme for Xcode. Compatible with all modern versions of Xcode since 2013!
Solarized Dark Theme for Xcode. Compatible with all modern versions of Xcode since 2013!

Solarized Dark for Xcode Note I've moved away from using Solarized to a Night-Shift/Dark-Mode-friendly palette of my own creation; Cognac. It's availa

Task-Manager - Task Manager App With Swift
Task-Manager - Task Manager App With Swift

Task-Manager It's typical task manager where user can assign the importance, def

🌸 Powerful Codable API requests builder and manager for iOS.
🌸 Powerful Codable API requests builder and manager for iOS.

This lib is about network requests with blackjack, roulette and craps! Using it you will be able to convert your massive API layer code into an awesom

AwaitKit is a powerful Swift library which provides a powerful way to write asynchronous code in a sequential manner.
AwaitKit is a powerful Swift library which provides a powerful way to write asynchronous code in a sequential manner.

AwaitKit is a powerful Swift library inspired by the Async/Await specification in ES8 (ECMAScript 2017) which provides a powerful way to write asynchronous code in a sequential manner.

The most power-efficient and lightweight iOS location manager for Swift and ObjC
The most power-efficient and lightweight iOS location manager for Swift and ObjC

IngeoSDK for iOS Overview IngeoSDK is a power-efficient location manager for iOS (Swift and Objective-C), which extends and improves CoreLocation. It

SwiftyReachability is a simple and lightweight network interface manager written in Swift.
SwiftyReachability is a simple and lightweight network interface manager written in Swift.

SwiftyReachability is a simple and lightweight network interface manager written in Swift. Freely inspired by https://github.com/tonymillion/Reachabil

Tranquillity is a lightweight but powerful dependency injection library for swift.
Tranquillity is a lightweight but powerful dependency injection library for swift.

DITranquillity Tranquillity is a lightweight but powerful dependency injection library for swift. The name "Tranquillity" laid the foundation in the b

VEditorKit - Lightweight and Powerful Editor Kit built on Texture(AsyncDisplayKit)
VEditorKit - Lightweight and Powerful Editor Kit built on Texture(AsyncDisplayKit)

VEditorKit provides the most core functionality needed for the editor. Unfortunately, When combined words are entered then UITextView selectedRange will changed and typingAttribute will cleared. So, In combined words case, Users can't continue typing the style they want.

Willow is a powerful, yet lightweight logging library written in Swift.

Willow Willow is a powerful, yet lightweight logging library written in Swift. Features Requirements Migration Guides Communication Installation Cocoa

A Lightweight But Powerful Color Kit (Swift)
A Lightweight But Powerful Color Kit (Swift)

BCColor A lightweight but powerful color kit (Swift) Features Pick Colors From Image Generate Monochrome Image Support Hex Color Style Lighten / Darke

A lightweight and powerful editor for localizing iOS, macOS, tvOS, and watchOS applications.
A lightweight and powerful editor for localizing iOS, macOS, tvOS, and watchOS applications.

It is Strings but with a Z 😬 Loved the project? Please share it with your friends and give it a ⭐️ Stringz is a lightweight and powerful editor that

Comments
  • API improvement suggestions or convenience API suggestions

    API improvement suggestions or convenience API suggestions

    Would it be possible to improve the usage of this awesome tool or add a convenience API?

    Room for improvement

    IMO the API for simple accessing e.g. a color form a View is pretty tedious. In every View one has to repeat the same 2 steps:

    1. Adding the property-wrapper
    @ThemeProviding<Theme> var themeProvider
    
    1. Passing the themeProvider to the View Modifier
    .foregroundColor(on: themeProvider, for: .foregroundColor)
    

    Suggestion

    Wouldn't it be way easier if we could get rid of points 1 and point 2? This would lead to a usage similar to:

    .foregroundColor(.foregroundColor)
    

    I saw that there is a lot of generic usage involved which could make this tedious.

    Possible Convenience API

    However, what I did in the meantime was to add the above suggestion as an extension to the Package without any internal changes needed.

    What I did was creating new ViewModifiers that encapsulates adding the PropertyWrapper and the need of passing the themeProvider again to the existing ViewModifiers.

    struct ThemedForegroundColorViewModifier: ViewModifier {
        @ThemeProviding<Theme> private var themeProvider
        private let asset: Theme.ThemeAsset.ColorAsset
    
        init(asset: Theme.ThemeAsset.ColorAsset) {
            self.asset = asset
        }
    
        func body(content: Content) -> some View {
            content
                .foregroundColor(on: themeProvider, for: asset)
        }
    }
    
    extension View {
        func foregroundColor(_ asset: Theme.ThemeAsset.ColorAsset) -> some View {
            self.modifier(ThemedForegroundColorViewModifier(asset: asset))
        }
    }
    

    Usage would look like exactly the same as above

    Similar things could be achieved for Color

    This requires a separate View as we need a custom init.

    struct ThemedColor: View, ShapeStyle {
        @ThemeProviding<Theme> private var themeProvider
        private let asset: Theme.ThemeAsset.ColorAsset
    
        init(_ asset: Theme.ThemeAsset.ColorAsset) {
            self.asset = asset
        }
    
        var body: some View {
            Color(on: themeProvider, for: asset)
        }
    }
    

    The usage would look like this:

    ThemedColor(.backgroundColor)
    
    enhancement 
    opened by stonko1994 2
  • Update README with note how to support Xcode Previews

    Update README with note how to support Xcode Previews

    I had a hard time figuring out why Xcode Previews no longer work after adding and using SwiftTheming in one of my Views.

    In order to make Xcode Previews working as well one need to add the setup code to the Previews as well.

    struct View_Preview: PreviewProvider {
        static var previews: {
            AnyView()
                .themeProviding(defaultTheme: Theme.sampleTheme, defaultAppearance: .system)
        }
    }
    
    invalid 
    opened by stonko1994 1
Releases(v2.0.0)
  • v2.0.0(Aug 29, 2022)

    What's new in Version 2.0.0?

    • As Version 2.0.0 is intended to provide a better developer experience, the API has been changed as below.
      • The API comes with the new style of declaration of themes.
      • To provide default theme and appearance, it starts using DefaultTheming instead of injecting default values into themeProviding(defaultTheme:defaultAppearance:).
      • It no longer uses the generic types in Themed and ThemeProvider.
      • All different types of asset is needed to declare separately instead of defining in value type conforming to Assetable.
      • To access interface elements (colors, images, etc), it is no longer required to pass the instance of ThemeProvider so that all interface elements can be initialized with respective asset keys.

    To see more, pls read MigrationGuide.md.

    • SwiftTheming provides the documentation that helps developers explore the API in ease.
    • Version 2.0.0 includes unit testing that covers around 95% of the API.
    Source code(tar.gz)
    Source code(zip)
  • v1.1.1(Jun 23, 2022)

  • v1.1.0(Mar 20, 2022)

    What's new in Version 1.1.0?

    • Add ThemeProviding property wrapper in purpose of clean syntax instead of using EnvironmentObject.
    • Add a test case for ThemeProviding
    Source code(tar.gz)
    Source code(zip)
  • v1.0.1(Jan 2, 2022)

  • v1.0.0(Dec 11, 2021)

Owner
Dscyre Scotti ο£Ώ
he/him, 20, ios developer, augmented reality enthusiast, β˜•οΈ drinker, nerd, living under the injustice, warriors πŸ€
Dscyre Scotti ο£Ώ
πŸ‘•πŸ‘š Theme management in Swift

Themes Story Ever want to support Night mode? Or skin the app differently depending on the seasons? Or toggle features according to paid status? Well,

Khoa 238 Dec 26, 2022
A Publish theme. ckitakishi.com is built with PaletteTheme

PaletteTheme A Publish theme. ckitakishi.com is built with PaletteTheme. Features Simple and fast Mobile friendly Support both Light/Dark mode Customi

Yuhan Chen 10 Nov 29, 2022
This repository contains 🎨 My Xcode theme that I use. It is compatible with all versions of Xcode.

DRL Xcodetheme Installation Automatic (via script) ./install.sh which will install the file in Xcode FontAndColorThemes directory. Restart Xcode Go t

durul dalkanat 19 Oct 21, 2022
Theme handling macOS Appkit (Swift/Objective-C)

DSFAppearanceManager A class for simplifying macOS appearance values and detecting setting changes (Swift/Objective-C). Why? If you're performing cust

Darren Ford 8 Nov 1, 2022
Solarized Dark Theme for Xcode. Compatible with all modern versions of Xcode since 2013!

Solarized Dark for Xcode Note I've moved away from using Solarized to a Night-Shift/Dark-Mode-friendly palette of my own creation; Cognac. It's availa

Arthur Ariel Sabintsev 365 Nov 25, 2022
A CSS-like style library for SwiftUI.

The missing CSS-like module for SwiftUI

hite 112 Dec 23, 2022
🎨 Powerful theme/skin manager for iOS 9+ 主钘/捒肀, ζš—θ‰²ζ¨‘εΌ

Introduction - Demos - Installation - Documents - FAQ - Contribution - δΈ­ζ–‡ζ–‡ζ‘£ Screenshot Running:open SwiftTheme.xcworkspace, run target PlistDemo Intro

Gesen 2.4k Jan 1, 2023
πŸ§›πŸ»β€β™‚οΈ Dark theme for SwiftUI

Dracula for SwiftUI A dark theme for SwiftUI. Install All instructions can be found at draculatheme.com/swiftui. Team This theme is maintained by the

Dracula Theme 14 Jul 26, 2022
SwiftUI module library for adding seasons theme animations to your app

HolidayThemes SwiftUI module library for adding seasons theme animations to your app. Requirements iOS 13.0+ Xcode 12.0+ Installation Swift Package Ma

null 2 Mar 7, 2022
A powerful SwiftUI Architecture that merges Redux to the functional world of Swift. While bringing powerful workflows to streamline CoreML/Metal/IPFS usage in the Apple ecosystem.

GraniteUI - v0.0 - WIP A powerful SwiftUI Architecture that merges Redux event handling and state management with functional programming. While bringi

Kala 2 Dec 22, 2022