techniques

Theming

System Text-to-Speech Ready
Slide: 0:00 / 0:00
Slide 1 of 0Interactive Deck

Full Lesson Reference

Modern apps support light and dark modes. This guide covers how to implement theme systems and handle system preference detection.

System Preference Detection

How it works

  • Operating systems expose light/dark preference
  • Apps can read and respond to this setting
  • Preference can change while app is running

Web: prefers-color-scheme

terminal
@media (prefers-color-scheme: dark) {
  /* dark mode styles */
}

SwiftUI: colorScheme

  • .preferredColorScheme() modifier
  • @Environment(\.colorScheme) to read current
  • Automatic with semantic colors

Prompting for system detection

terminal
Detect the system color scheme preference.
Default to the user's system setting but allow
manual override.

Color Scheme Architecture

Semantic color naming

Instead of literal colors, use semantic names:

  • background not white
  • text-primary not black
  • surface not gray-100
  • accent not blue-500

Color pairs

Each semantic color needs light and dark values:

terminal
background:
  light: #FFFFFF
  dark: #121212

text-primary:
  light: #1A1A1A
  dark: #F5F5F5

surface:
  light: #F5F5F5
  dark: #1E1E1E

Beyond black and white

  • True black (#000) can be harsh in dark mode
  • Off-black (#121212) is easier on the eyes
  • Consider reduced contrast for less important text
  • Accent colors may need different values per theme

Design Token Approach

Setting up tokens

terminal
Set up a theme system with these tokens:

Light theme:
- Background: #FFFFFF
- Surface: #F8FAFC
- Text: #1E293B
- Accent: #2563EB

Dark theme:
- Background: #0F172A
- Surface: #1E293B
- Text: #F1F5F9
- Accent: #3B82F6

CSS custom properties (Web)

terminal
:root {
  --bg: #ffffff;
  --text: #1a1a1a;
}

[data-theme="dark"] {
  --bg: #121212;
  --text: #f5f5f5;
}

SwiftUI Color assets

  • Create color sets in Assets.xcassets
  • Define "Any Appearance" and "Dark" variants
  • Reference by name: Color("background")

Theme Switching

User preference storage

  • Save user choice (system/light/dark)
  • Persist across sessions
  • Default to system preference

Implementation prompts

terminal
Add a theme toggle in settings.
Options: System (default), Light, Dark.
Save the preference so it persists.

Smooth transitions

terminal
Add a smooth transition when switching themes.
The colors should fade, not snap instantly.

Manual override

terminal
Let users override the system setting.
Add a three-way toggle: Light / System / Dark

Platform-Specific Patterns

Web

  • CSS custom properties for colors
  • data-theme attribute on html/body
  • JavaScript for toggle and persistence
  • Prefers-color-scheme media query for default

SwiftUI

  • Asset catalog color sets
  • @Environment(\.colorScheme)
  • preferredColorScheme() modifier
  • Automatic with semantic system colors

React Native

  • Appearance module for system detection
  • Context for app-wide theme
  • Styled-components or emotion for dynamic theming

Beyond Light/Dark

Multiple themes

  • Brand themes
  • High contrast mode
  • Seasonal themes
  • User-customizable themes

High contrast

terminal
Add a high contrast mode option.
Increase the contrast ratios beyond standard.

Accent color customization

terminal
Let users choose their accent color from
a set of preset options.

Testing Themes

What to check

  • All text remains readable
  • Interactive elements are distinguishable
  • Images and icons adapt appropriately
  • No hard-coded colors leaking through

Testing prompts

terminal
Switch to dark mode. Check that all
components adapt correctly and nothing
uses hard-coded light colors.

Edge cases

  • Images on backgrounds (may need borders)
  • Charts and data visualizations
  • Third-party embeds
  • User-generated content

Example Prompts

Basic dark mode

terminal
Add dark mode support. Use semantic colors
that adapt to the system preference.

Theme toggle

terminal
Add a theme toggle in the header.
It should cycle through: light, dark, system.
Show an icon for the current mode.

Smooth transitions

terminal
When the theme changes, animate the color
transition over 200ms so it's not jarring.

Custom accent color

terminal
Let users pick an accent color for the app.
Offer 6 preset colors. Save their choice.

Complete theme system

terminal
Set up a complete theme system:
- Light and dark modes
- System preference detection
- Manual override with persistence
- Semantic color tokens
- Smooth transitions when switching

Make It Stick with a Skill File

If you want Claude to use semantic color tokens, consistent spacing scales, and proper typography hierarchy automatically, drop the Design System skill file into your project. It pairs well with theming — your theme handles light/dark, the design system handles everything else.

What You'll Learn

  • How to detect system color preferences
  • Semantic color naming approaches
  • Design token architecture for themes
  • Implementing theme switchers
  • Testing across different modes

Exercises

  1. Use the "Complete theme system" prompt to add light/dark support to a project, then verify with the "Testing prompts" example that no hard-coded light colors leak through in dark mode.
  2. Refactor at least three literal color references (like white or blue-500) into semantic tokens (background, accent) so the theme can swap them per mode.
  3. Add a three-way Light / System / Dark toggle that persists across sessions, then reload the app to confirm your choice survives.