Themes let you customize the appearance of your site, with built-in support for light and dark modes.
Themes conform to the Theme
protocol, which provides sensible defaults for both light and dark appearances. When creating a theme, you specify its colorScheme
to determine whether it uses light or dark variants of Ignite’s default styles.
struct MyTheme: Theme {
var colorScheme: ColorScheme = .light // or .dark
// Override any theme properties you want to customize
var syntaxHighlighterTheme: HighlighterTheme = .githubLight
}
You can create a base theme protocol that provides common values for multiple themes. This allows you to share styling between themes while still having color scheme specific values for properties you haven’t explicitly set.
// Base protocol with shared theme values
protocol BaseTheme: Theme {}
// Default implementation for shared values
extension BaseTheme {
var accent: Color { Color(hex: "#FF0000") }
var secondaryAccent: Color { Color(hex: "#00FF00") }
}
// Light theme implementation
struct LightTheme: BaseTheme {
var colorScheme: ColorScheme = .light
// Uses shared accent/secondaryAccent colors
// Other values default to stock light theme colors
}
// Dark theme implementation
struct DarkTheme: BaseTheme {
var colorScheme: ColorScheme = .dark
// Uses shared accent/secondaryAccent colors
// Other values default to stock dark theme colors
}
To enable themes in your site, add them to your site configuration:
struct ExampleSite: Site {
var lightTheme: (any Theme)? = LightTheme()
var darkTheme: (any Theme)? = DarkTheme()
var alternateThemes: [any Theme] = [
SeaTheme(),
DesertTheme(),
ForestTheme()
]
}
Note: You can add additional themes through Site
’s alternateThemes
property.
You can disable either light or dark mode by setting the corresponding theme to nil
:
struct DarkOnlySite: Site {
var lightTheme: (any Theme)? = nil // Disable light mode
var darkTheme: (any Theme)? = DarkTheme()
}
struct LightOnlySite: Site {
var lightTheme: (any Theme)? = LightTheme()
var darkTheme: (any Theme)? = nil // Disable dark mode
}
Note: You must provide at least one theme (either light or dark). Setting both lightTheme
and darkTheme
to nil
will result in a build error.
You can access all available themes through the environment, making it easy to create a theme switcher. The SwitchTheme()
action lets users change themes dynamically.
struct ThemeSwitcher: HTML {
@Environment(\.themes) private var themes
var body: some HTML {
ForEach(themes) { theme in
Button(theme.name) {
SwitchTheme(theme)
}
}
}
}
Give the theme switcher at the bottom of this page a whirl to see this all in action. 👇
When using Material
, the correct variant (light or dark) will automatically be selected based on your theme’s colorScheme
value.
You can override the default Material
variant using the colorScheme()
method, which is useful when you want components to always use a specific appearance:
ZStack {
Image("/images/photos/dishwasher.jpg")
.resizable()
Text("Always Dark Material")
.font(.title3)
.containerRelativeFrame()
.background(.thinMaterial.colorScheme(.dark))
}
.clipped()
.cornerRadius(12)
Here’s an example using Material
: