Stylish
is a library that helps you quickly and easily create user styles when creating custom views in SwiftUI
.
In 2019, the UI paradigm shifted when Apple
introduced SwiftUI
. The styling and propagation of UI Components is very interesting, but styling with Environment is not free from naming duplication and customization.
Stylish
solves these problems to help you reduce boilerplate code and increase productivity.
- Swift 5.9+ (Macro Support)
- iOS 13.0+
- macOS 10.15+
- macCatalyst 13.0+
- tvOS 13.0+
- watchOS 6.0+
dependencies: [
.package(url: "https://github.com/wlsdms0122/Stylish.git", .upToNextMajor(from: "2.0.0"))
]
Using Stylish is straightforward. To create a styled component, add the @Stylish macro to your styles.
@Stylish
struct MyStyle {
var textColor: Color = .black
}
The @Stylish
macro automatically adopts the Stylish
protocol to manage configurations.
And you can access @Styles
property wrapper on your view to use Stylish
styles for custom component.
struct MyButton: View {
var body: some View {
Button {
} label: {
Text("Touch!")
.foregroundColor(styles.textColor)
}
}
@Styles(MyStyle.self)
private var styles
}
That's it! Now, modify the view using the configure(_:style:to:)
modifier.
struct ContentView: View {
var body: some View {
MyButton()
.configure(
MyButton.self,
style: \.textColor,
to: .green
)
}
}
The @Stylish
macro automactically add @Config
attribute on style properties.
When you create custom style like .buttonSyle(_:)
, you need to set default styles.
In SwiftUI
, properties specified by the user using the view modifier have the highest priority. However, in styling, subsequent styles should override even if the user sets the style.
MyButton()
.configure(MyButton.self, style: \.style, to: .card)
.configure(MyButton.self, style: \.foregroundColor, to: .green)
For example, with a card type MyButtonStyle
setting the foreground color of the button title to blue, subsequent styles should override this, similar to a real ButtonStyle
.
Utilize the @Config
property wrapper for this:
public struct CardMyButtonStyle: MyButtonStyle {
private struct Content: View {
var body: some View {
configuration.label
.configure(
MyButton.self,
style: \.foregroundColor,
to: styles.$foregroundColor(.blue)
)
}
private let configuration: Configuration
@Styles(MyButton.self)
var styles
init(_ configuration: Configuration) {
self.configuration = configuration
}
}
public func makeBody(_ configuration: Configuration) -> some View {
Content(configuration)
}
}
The projectedValue
of the @Config
property wrapper returns a function, which only returns the value you pass in if the property is not specified.
Any ideas, issues, opinions are welcome.
Stylish is available under the MIT license. See the LICENSE file for more info.