Tools: SwiftUI Dark Mode: The Complete Implementation Guide

Tools: SwiftUI Dark Mode: The Complete Implementation Guide

Source: Dev.to

The Basics: Color Scheme ## Use Semantic Colors ## Create a Theme System ## Preview Both Modes ## Common Mistakes ## Skip the Setup Dark Mode is no longer optional — users expect it. Here's how to implement it properly in SwiftUI. SwiftUI provides @Environment(\.colorScheme) to detect the current mode: But there's a better way... SwiftUI has built-in colors that adapt automatically: For full control, create a theme: Use it with environment: Always test both modes in previews: If you want Dark Mode already configured with a complete theme system, check out SwiftUI Starter Kit Pro. It includes a production-ready theme with automatic dark mode support. Questions? Drop them below! Follow @SwiftUIDaily for daily SwiftUI tips. Templates let you quickly answer FAQs or store snippets for re-use. Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment's permalink. Hide child comments as well For further actions, you may consider blocking this person and/or reporting abuse CODE_BLOCK: struct ContentView: View { @Environment(\.colorScheme) var colorScheme var body: some View { Text("Hello") .foregroundColor(colorScheme == .dark ? .white : .black) } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: struct ContentView: View { @Environment(\.colorScheme) var colorScheme var body: some View { Text("Hello") .foregroundColor(colorScheme == .dark ? .white : .black) } } CODE_BLOCK: struct ContentView: View { @Environment(\.colorScheme) var colorScheme var body: some View { Text("Hello") .foregroundColor(colorScheme == .dark ? .white : .black) } } CODE_BLOCK: Text("Adapts automatically") .foregroundColor(.primary) // Black in light, white in dark .background(Color(.systemBackground)) // White in light, black in dark Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: Text("Adapts automatically") .foregroundColor(.primary) // Black in light, white in dark .background(Color(.systemBackground)) // White in light, black in dark CODE_BLOCK: Text("Adapts automatically") .foregroundColor(.primary) // Black in light, white in dark .background(Color(.systemBackground)) // White in light, black in dark CODE_BLOCK: struct AppTheme { let background: Color let text: Color let accent: Color static let light = AppTheme( background: .white, text: .black, accent: .blue ) static let dark = AppTheme( background: Color(.systemGray6), text: .white, accent: .cyan ) } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: struct AppTheme { let background: Color let text: Color let accent: Color static let light = AppTheme( background: .white, text: .black, accent: .blue ) static let dark = AppTheme( background: Color(.systemGray6), text: .white, accent: .cyan ) } CODE_BLOCK: struct AppTheme { let background: Color let text: Color let accent: Color static let light = AppTheme( background: .white, text: .black, accent: .blue ) static let dark = AppTheme( background: Color(.systemGray6), text: .white, accent: .cyan ) } CODE_BLOCK: struct ThemeKey: EnvironmentKey { static let defaultValue = AppTheme.light } extension EnvironmentValues { var theme: AppTheme { get { self[ThemeKey.self] } set { self[ThemeKey.self] = newValue } } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: struct ThemeKey: EnvironmentKey { static let defaultValue = AppTheme.light } extension EnvironmentValues { var theme: AppTheme { get { self[ThemeKey.self] } set { self[ThemeKey.self] = newValue } } } CODE_BLOCK: struct ThemeKey: EnvironmentKey { static let defaultValue = AppTheme.light } extension EnvironmentValues { var theme: AppTheme { get { self[ThemeKey.self] } set { self[ThemeKey.self] = newValue } } } CODE_BLOCK: struct ContentView_Previews: PreviewProvider { static var previews: some View { Group { ContentView() .preferredColorScheme(.light) ContentView() .preferredColorScheme(.dark) } } } Enter fullscreen mode Exit fullscreen mode CODE_BLOCK: struct ContentView_Previews: PreviewProvider { static var previews: some View { Group { ContentView() .preferredColorScheme(.light) ContentView() .preferredColorScheme(.dark) } } } CODE_BLOCK: struct ContentView_Previews: PreviewProvider { static var previews: some View { Group { ContentView() .preferredColorScheme(.light) ContentView() .preferredColorScheme(.dark) } } } - .primary / .secondary — text colors - Color(.systemBackground) — main background - Color(.secondarySystemBackground) — grouped content - Hardcoding colors — Use semantic colors instead - Forgetting images — Use SF Symbols or provide dark variants - Not testing — Always preview both modes