Styled is a Type-Safe accessibility & theme management library in Swift.
- Color management & synchronization with OS
- Font management & synchronization with OS
- String-Interpolation Localization
- Image management (per Localization or provided lazily by an external resource)
- iOS 10.0+
- XCode 11+
- Swift 5.1+ (Swift 5.0 compatible)
CocoaPods is a dependency manager for Cocoa projects. For usage and installation instructions, visit their website. To integrate Styled into your XCode project, simply add the Styled dependency to your Podfile.
pod 'Styled'
Coming soon
Coming soon
To run the example project, clone the repo, and run pod install
from the root directory.
Don't forget to play with XCode accessibilities to see the results
This is how you'll be using Styled in a nutshell:
class CustomView: UIView {
var customColor: UIColor { didSet { /* Update UI Accordingly */ } }
}
let view = CustomView()
/// This is where all the magic happens
view.sd.backgroundColor = .background
/// It even works with custom defined variables 🤩
view.sd.customColor = .red
/// It also supports transformations 👽
view.sd.customColor = .blending(.red, with: .black) // Darkened red
Just by writing view.sd.customColor
Styled will gaurantee that everytime the ColorScheme
changes, your customColor
will get updated accordingly in the background, So you no longer need to worry about choosing the correct color or updating your UI everytime user changes accessibility options (Dark mode, font size, High contrast, etc).
This is how you define Color
s:
extension Color {
/// Color suitable for first-level labels
static let label: Self = "label"
/// Color suitable for second-level labels (i.e subtitle/description)
static let secondaryLabel: Self = "label.secondary"
/// Or custimized **red** for different schemes?
static let red: Color = "red"
}
And this is how you define ColorScheme
s:
extension Color {
struct LightScheme: ColorScheme {
func color(for color: Color) -> UIColor? {
switch color {
case .label: return UIColor.black
case .secondaryLabel: return UIColor.gray
default: fatalError("Uknown color \(color)")
}
}
}
struct DarkColorScheme: ColorScheme { ... }
}
And this is how you control which ColorScheme
the app should use:
// You can manually control the ColorScheme
Styled.Config.colorScheme = Color.LightScheme()
// Or You can update it with system's theme
Styled.Config.onUserInterfaceStyleDidChange {
switch $0 {
case .dark: return .replace(with: Color.DarkScheme())
default: return .replace(with: Color.LightScheme())
}
}
// Or if you defined your colors in AssetsCatalog:
Styled.Config.colorScheme = Color.DefaultScheme()
And That's it! You can also take the same approach to define Image
s, Font
s and LocalizedString
s.
Defining Font
s and FontScheme
s is almost the same as defining Colors.
For keeping the application in sync with device's font size, you can use the following method:
Styled.Config.onContentSizeCategoryDidChange { _ in .update }
.update
will not change the current FontScheme
, but will trigger a font update on all Styled elements.
Defining Image
s and ImageScheme
s is the same as defining Colors.
LocalizedString
by default will look inside Localizable.strings
& Localizable.stringsdict
, but you can take ownership of Localization management just like Color
s/Font
s/Image
s by defining your own LocalizedStringScheme
s.
You can also define common words or sentences that you use throughout the application just like Color:
extension LocalizedString {
static let ok: LocalizedString = "ok"
static let cancel: LocalizedString = "cancel"
}
And just use it like other Styled variables:
label.sd.text = .ok
LocalizedString
also supports string-interpolation to translate localizations.
By default all interpolations will be replaced with "%@"
before being queried
For example the following interpolation:
label.sd.text = "lastIndex is \(count - 1))"
Will look inside Localizable.strings
(or Localizable.stringsdict
or your personalized LoaclizedStringScheme
) for the key "lastIndex is %@"
to fetch its translation. So this is what inside Localizable.strings
file should look like:
// English
"lastIndex is %@" = "lastIndex is %@";
// Persian
"lastIndex is %@" = "آخرین اندیس %@ است";
You can also customize the specifier inside the interpolation method to use something else instead of "%@"
:
label.sd.text = "lastIndex is \(count - 1, specifier: "%d")"
And this will generate the key "lastIndex is %d"
You can always add your personalized functionalities to the LocalizedString.StringInterpolation
to make your String-Interpolation localization suit your needs.
FarzadShbfn, [email protected]
Styled is available under the MIT license. See the LICENSE file for more info.