React Native diary #3: dark mode

Even though Epilogue 1.0 was simple, it did support Dark Mode on iOS. I always run my phone in Dark Mode, so I didn’t want to lose that when rewriting Epilogue in React Native.

There are a handful of helper utilities to access iOS-only features in React Native, like Platform.isPad . There’s also useColorScheme, which can be used to check if we’re running in Dark Mode:

const is_dark = (useColorScheme() == "dark");

There doesn’t appear to be built-in support in React Native to use different sets of styles automatically. There are, however, at least a few third-party libraries to make this easier, including various dynamic stylesheets and React Navigation’s themes. I started to go down that rabbit hole, then stopped… There’s a lot to learn and I’d rather adopt a quick “worse is better” approach to first get a feel for how painful it is to style my views manually.

I have a Styles.js source file that looks like this, controlling layout and colors for UI elements in Epilogue:

import { StyleSheet } from "react-native";

export default StyleSheet.create({
  bookTitle: {
    marginTop: 8,
    paddingLeft: 7
  },
  bookAuthor: {
    paddingTop: 4,
    paddingLeft: 7,
    color: "#777777"
  },
  ...
}

To use this style in JSX, I have something like this:

<Text style={styles.bookAuthor}>Neil Gaiman</Text>

To support Dark Mode, I’ve added a special “dark” field to the styles object. This will only have style properties that I want to override from the default light mode. In the case of bookAuthor, there’s no need to change the padding, just the text color:

bookAuthor: {
  paddingTop: 4,
  paddingLeft: 7,
  color: "#777777"
},
dark: {
  bookAuthor: {
    color: "#FFFFFF"
  }
}

Back to the JSX, I check my is_dark variable and then reference a different set of styles. JSX lets me pass an array of styles, so we’ll include both the light mode version (styles.bookAuthor) and then the dark value (styles.dark.bookAuthor) that will override the color:

<Text style={is_dark ? [ styles.bookAuthor, styles.dark.bookAuthor ] : styles.bookAuthor}>Neil Gaiman</Text>

Here are a couple screenshots showing each mode side by side:

Epilogue light screenshot Epilogue dark screenshot

The JSX code is admittedly a little clunky. I can see how it could be cleaned up and more readable with other solutions. But the app only has a few screens, so I’m going to run with this for now.

Manton Reece @manton