Next.js Discord

Discord Forum

Best way to implement darkmode

Unanswered
Persian posted this in #help-forum
Open in Discord
PersianOP
Hello 👋 , i'm looking for some tips to implement the best/correct way darkmode/multitheme with tailwind in a Next project please:

i have created a client component with Context and all the logic associated with, then i imported it in MainLayout()
it works just fine but i'm not happy with the jsx code ContextComponent return: needed to put 2 div to make it work :
1 to catch dark class (to simulate the <html> tag we usually use), then a second to mimic the <body> tag with all global propieties.

I saw several people recommand to use a third-party libary called "next-theme" but after checking the git repo it seems not maintened since nearly one year.

Thanks 🙌 !
ContextComponent : 

export default function ThemeProvider({
  children,
}: {
  children: React.ReactNode
}) {
  const [isToggle, setIsToggle] = useState(false)
  const toggle = () => setIsToggle((p) => !p)
  const theme = isToggle ? "dark" : ""

  return (
    <themeContext.Provider value={{ theme, isToggle, toggle }}>
      <div className={theme}>
        <div className="flex min-h-screen w-full flex-col bg-purple-400 text-black transition-all dark:bg-blue-950 dark:text-white">
          {children}
        </div>
      </div>
    </themeContext.Provider>
  )
}

MainLayout :
 
export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="fr">
      <body className={`${inter.className}`}>
        <ThemeProvider>
          <Navbar />
          <main className="mx-auto flex w-10/12 flex-col py-3 text-center">
            {children}
          </main>
        </ThemeProvider>
      </body>
    </html>
  )
}

11 Replies

European sprat
You can see in this repo one way to do it. I think this is a pretty common pattern:

https://github.com/shadcn-ui/next-template
@Persian Hello 👋 , i'm looking for some tips to implement the best/correct way darkmode/multitheme with tailwind in a Next project please: i have created a client component with `Context` and all the logic associated with, then i imported it in MainLayout() it works just fine but i'm not happy with the jsx code `ContextComponent` return: needed to put 2 div to make it work : 1 to catch dark class (to simulate the `<html>` tag we usually use), then a second to mimic the `<body>` tag with all global propieties. I saw several people recommand to use a third-party libary called "next-theme" but after checking the git repo it seems not maintened since nearly one year. Thanks 🙌 ! typescript ContextComponent : export default function ThemeProvider({ children, }: { children: React.ReactNode }) { const [isToggle, setIsToggle] = useState(false) const toggle = () => setIsToggle((p) => !p) const theme = isToggle ? "dark" : "" return ( <themeContext.Provider value={{ theme, isToggle, toggle }}> <div className={theme}> <div className="flex min-h-screen w-full flex-col bg-purple-400 text-black transition-all dark:bg-blue-950 dark:text-white"> {children} </div> </div> </themeContext.Provider> ) } typescript MainLayout : export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( <html lang="fr"> <body className={`${inter.className}`}> <ThemeProvider> <Navbar /> <main className="mx-auto flex w-10/12 flex-col py-3 text-center"> {children} </main> </ThemeProvider> </body> </html> ) }
I saw several people recommand to use a third-party libary called "next-theme" but after checking the git repo it seems not maintened since nearly one year.
it still works well. if it already works well there are few reasons to update it
next-themes is still the best library for theme management in nextjs, i haven't seen anything coming close to it
Brown bear
use daisy ui
https://daisyui.com/
layout.js
//
export default function RootLayout({ children }) {
return (
<html data-theme="dark">
<body>
<Navbar />
{children}
</body>
</html>
);
}
//
tailwind.config.js
daisyui: {
themes: ["light" , "dark"],
},
advance example :

tailwind.config.js daisyui: { themes: ["winter" , "night"], },
layout.js export const THEMES = { light: "winter", dark: "night", }; export const DEFAULT_THEME = THEMES.light; // Set export default function RootLayout({ children }) { return ( <html data-theme={DEFAULT_THEME}> <body> <Navbar /> {children} </body> </html> ); }

navbar.js import { THEMES, DEFAULT_THEME } from "../app/layout"; export default function Navbar() { const [mode, setMode] = useState(DEFAULT_THEME); useEffect(() => { document.documentElement.setAttribute("data-theme", mode); }, [mode]); function handleClick() { setMode(mode === THEMES.light ? THEMES.dark : THEMES.light); }
@European sprat You can see in this repo one way to do it. I think this is a pretty common pattern: https://github.com/shadcn-ui/next-template
PersianOP
it's seems to be a good template to understand how to implement next-themes; Thank you 🙌
@Brown bear use daisy ui
PersianOP
Thanks for your reply and example 🙂 i know daisy but never used it, it will be a good first time to try it out 🙌
@Persian Thanks for your reply and example 🙂 i know daisy but never used it, it will be a good first time to try it out 🙌
Brown bear
Like you, this is my first time using Daisy. However, after using it, I realized how much time it can save me. With Daisy, there’s no need to create themes like dark mode or light mode because they’re already built-in. Additionally, it has almost all the components you need and is easy to customize since it’s based on Tailwind.