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:
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.