Themes and Dark Mode

Dark Mode and Custom Themes in NativeWind

The quickest dark mode is the dark: variant: bg-white dark:bg-slate-900 switches with the device's appearance. It doubles every color class, though. BookNest instead names its colors after their roles and stores the values in CSS variables, which one media query redefines for dark mode:

global.css: BookNest's palette as CSS variables (excerpt)CSS
:root {
  --brand: 21 101 192;                /* #1565c0 */
  --surface: 255 255 255;
  --page: 236 239 241;                /* #eceff1 */
  --ink: 33 33 33;
}
@media (prefers-color-scheme: dark) {
  :root {
    --brand: 144 202 249;             /* #90caf9 */
    --surface: 27 42 65;
    --page: 11 19 32;
    --ink: 227 242 253;
  }
}
tailwind.config.js: role names that read the variables (excerpt)JSX
      colors: {
        brand: 'rgb(var(--brand) / <alpha-value>)',
        surface: 'rgb(var(--surface) / <alpha-value>)',
        page: 'rgb(var(--page) / <alpha-value>)',
        ink: 'rgb(var(--ink) / <alpha-value>)',
      },

Components now say bg-surface text-ink and never mention dark mode; <alpha-value> keeps text-ink/60 working. Two settings make the switch reach the app. Expo 6,418 apps follow the system appearance only with "userInterfaceStyle": "automatic" in app.json (BookNest had "light"), and navigation chrome is not NativeWind's: the root layout passes DarkTheme or DefaultTheme, which Expo Router 57 6,418 exports, to its ThemeProvider. To let users override the system, NativeWind's useColorScheme() returns setColorScheme():

src/demos/SchemeSwitch.tsx: System, Light and Dark buttons (excerpt)TSX
  const { colorScheme, setColorScheme } = useColorScheme();
        {choices.map((c) => (
          <Pressable key={c} onPress={() => setColorScheme(c)}

Tapping Dark, then System, then switching the emulator's night mode on and off (adb -s emulator-5554 shell cmd uimode night yes) logged from the root layout:

Output of 180
 LOG  color scheme: dark
 LOG  color scheme: light
 LOG  color scheme: dark
 LOG  color scheme: light

For themes chosen at run time (a seasonal palette, a user's accent color), vars({ '--brand': '46 125 50' }) from nativewind returns a style that redefines the variables for one subtree.