Fixing Disqus 'Auto' theme switching when using Next.js + next-themes
In my last post about the amazing Blaugust event (Opens in a new tab), I've been mentioning my issue with setting up my Next.js (Opens in a new tab) site combined with next-themes (Opens in a new tab) and Disqus (Opens in a new tab) commenting platform.
This article is here to make sure I can share my solution, as for as simple it was it might help some people that stumble upon it. Let's start first with what issue I had, what I've done, so that we can walk together through the solution!
What was the issue
After following the Step-By-Step Guide to Adding Dark Mode and Multiple Themes to Your Next.js App (Opens in a new tab) written by Luis Cadillo (Opens in a new tab) (thank you pal!), I found myself with a neat Dark mode but my Disqus embed (installed through disqus-react npm package (Opens in a new tab)) would not update its theme properly, despite its theme settings being on Auto
.
I checked that the settings in <sitename>.disqus.com/admin/settings/general/
were correct, but that didn't help.
The solution
My initial challenge was understanding how Disqus determined which theme to show in the page. Browsing the documentation I stumbled on a piece of useful information:
Light vs. dark color scheme
A light or dark color scheme is automatically selected based on your site's stylesheets.
How is the color scheme determined?
- The light scheme is loaded when the text color Disqus inherits from your site has >= 50% gray contrast: between color: #000000; and color: #787878;
- The dark scheme is loaded in all other instances.
This allowed me to understand how the color scheme in Disqus was determined, but not yet why my changes wouldn't work. White text on a white background isn't quite the 'Auto' mode I was hoping for!
Searching for some help in StackOverflow (Opens in a new tab), I found my very same problem but no answer to it: Disqus theme not matching background when changing blog theme from dark to light (Opens in a new tab). Despite not finding a solution, I found some comfort in seeing that other peeps had my same problem and that it wasn't just me being... well... dumb xD
A little bit more digging and googling around brought me to another StackOverflow post, Disqus comments Dark mode renders with white background (Opens in a new tab) where Ken Mueller (Opens in a new tab) mentions to "Remove the <meta name="color-scheme" content="dark" /> from your document.".
Now, I didn't have such a thing in my Next.js ecosystem, but I noticed that next-themes applied a style="color-scheme: dark;"
to my main HTML tag.
1<html lang="en" class="dark" style="color-scheme: dark;">
Since messing around with the inspector costs nothing, I've simply tried to remove the content of style
and don't you know... it worked!
Checking next-themes documentation (Opens in a new tab), reading the codebase and bashing my head a little, I seem to understand that this HTML style change comes from the enableColorScheme
setting of next-themes, which by default is set as true
, but for my case would need to be set false
.
1const MyApp = ({ Component, pageProps }: AppProps) => { 2 return ( 3 <> 4 <ThemeProvider attribute="class" enableColorScheme={false}> 5 <Provider store={store}> 6 <Component {...pageProps} /> 7 </Provider> 8 </ThemeProvider> 9 </> 10 ); 11}; 12 13export default MyApp;
Wohoo! Works like a charm!
But no, wait!
Now if I am in an article page and I want to switch the theme there, my <DiscussionEmbed>
component from disqus-react (Opens in a new tab) won't update automatically! So what do we do now?
I happen to have this component wrapped in a container for easier setup on my page, and I know that React would re-render a component should its key change... so 1 + 1 I had my 2:
1const DisqusComments: FC<DisqusCommentsProps> = ({ url, slug, title }) => { 2 // Import the name of the theme with useTheme() hook 3 // from next-themes 4 const { theme } = useTheme(); 5 6 const disqusConfig = { 7 url: url, 8 identifier: slug, 9 title: title, 10 }; 11 12 // Use it as a key={theme} for the DiscussionEmbed component 13 // so that it will re-render should the theme change 14 return ( 15 <div className="my-14"> 16 <DiscussionEmbed key={theme} shortname={"oh-no"} config={disqusConfig} /> 17 </div> 18 ); 19}; 20 21export default DisqusComments;
Basically, I'll use the name of the theme to determine whether the Disqus component should re-render, and should someone change the theme in an article page, the Disqus comment section will reload with the correct theme!
At last, all I wanted!
Let me know if this helped you somehow, if you had the same issue or if somehow it brought you some help understanding a bit more about the problem for your own specific case!