🌑 gatsby dark mode
You're not one of the cool kids nowadays if you don't have a dark mode on your site. So I figured it was time to join the club and get this implemented. My previous work converting styled component variables to css custom properties laid the groundwork for this feature.
Here's the full pull request, but I gotta warn you, it's pretty messy.
🎨 color intentions
The first step was to separate the colors from their intentions. You may have not heard the term intention before, but it essentially means the intended use of a color. For example, you could have intentions like heading-color
, text-color
, or background-color
. This gives us a layer of abstraction, so we can swap out light and dark values based on the color theme.
🎣 app context
Next, I needed a way to hold the selected color theme in global state. I used the Context
API to provide the theme to the application. The context wraps the Layout
component, and I used gatsby-plugin-layout to render the Layout
on every page. This plugin also has the benefit of preserving the context values through page navigation.
🔆 toggle button
Finally, I tie everything together with a toggle button. This button shows a moon icon if the current theme is light
, and a sun icon if the current theme is dark
. The theme toggle uses the App
context to get and set the current theme
when clicked.
When the theme
changes, a useEffect
runs and updates the custom properties for the color intentions. At this time I only have two intentions that need updating. In the future, if I have more properties to change, this effect can be improved by creating a css
class that overrides the properties, and applying it to the :root
element.
🌟 improvements
While this dark modes works very well, and persists through page navigation, it's far from complete. It still lacks the following features:
- initialize the color theme to match system preferences
- persist the color theme across page reloads
Josh Comeau wrote a great article about the perfect dark mode, which I'll use as a reference to implement these last two features.
Give dark mode a try, click the moon at the top of the page!