This package is part of the SNAP suite.
A toolset to abstract Colors, Fonts, Icons and Numbers of a multi-platform SwiftUI app. Define semantic attributes in a Theme
and apply them to your views for a consistent UI with maintainability in mind.
Consistency in look and feel is important. Especially for a growing app project, when you decide to tweak a few attributes or need adjustments to fit platform changes or design trends. Goal of SnapTheme
is to define visual attributes in a single place, to allow: A consistent UI with simple adjustments and quick experiments, but strong maintainability.
Instead of defining design attributes all over the place, you register a semantic key, assign a definition and use it in your SwiftUI views. You can also define multiple Themes to let the user choose it's favorite.
Theme
comes with:
- Base attributes (Color, Font, Icon, Number) and composed attributes (Surface, Background, TextSurface).
- A preset of common semantic definitions for these attributes (e.g.
.textTitle
,.textSubtitle
) with platform specific default values. - ViewModifier to apply them to your views.
- Wrapper of stock SwiftUI views to set attributes from Theme definitions (e.g.
ThemeVStack(spacing:
)). - Convenience views for common layout and style tasks (e.g.
ThemeScreen
,ThemeElement
).
The Theme is injected in the Environment
to be available to ViewModifier and Views.
Fonts and Numbers are scaled by DynamicType by default. This brings some additional benefits:
- UI sizes (paddings, spacings, ...) defined by the Theme will scale with DynamicType.
- By adjusting the Themes scale factor, the whole UI can be zoomed by a simple value change.
The Theme comes with some presets and is easy to use and customize.
Override preset attributes in a custom Theme:
let theme = Theme(
colors: [
.accentColorBase : .color(.purple)
],
...
)
And/or define your own attributes:
extension Theme.ColorKey {
static let exampleColor = Theme.ColorKey("exampleColor", default: .color(.purple))
}
contentView.theme(apply: theme)
Text("Example").color(.exampleColor)
Represent a semantic meaning of the color (.foreground
, .background
, .accent
, .destructive
).
They do not describe the color or specific use case (, .red
)..buttonLabel
A Surface represents a ShapeStyle
, either a color, material or gradient.
Represents a semantic meaning of text (.textTitle
, .textSubtitle
) and assigns a FontDefinition
.
Represents a semantic meaning of a visual indicator and assigns an image.
Represents a specific value. Scaled by dynamic type.
Assigns a Surface
to a font.
Defines the background of a semantic layout element (.screen
, .content
, .contentSecondary
) by assigning a Surface
and a highlight Surface
.
A demo of the Theme in action is available at snap-app-theme-demo. It provides a reference for all preset attributes, demonstrates the default values and provides some configuration sets to change attributes in the app.
Key and default value.
Values registered for a ThemeKey
.
Examples: BackgroundValue, ColorValue (TextSurface), FontValue, IconValue, NumberValue
Modifier using ThemeKey
s to apply the configured values on a view.
Examples: .theme(background:)
, .theme(color:)
, .theme(text:)
, .theme(padding:)
Generic container views used for layout. Basic building blocks of to build a screen.
Examples: ThemeScreen
, ThemeHStack(spacing:)
, ThemeElement
Views that show content and use ThemeKey
s to configure style and layout.
Examples: ThemeLabel(icon:)
, ThemeCornerView(icon:)
, ThemeRectangle(cornerRadius:)
Container use ThemeKey
s to layout content.
Examples: ThemeCloseContainer
, ThemeSectionHeaderContainer
Definitions of SwiftUI styles using ThemeKey
s.
Examples: ThemeButtonStyle
, ThemeLabelStyleTag