React 18 Themes
🤟 👉 Unleash the Power of React Server Components
This project is inspired by next-themes
. next-themes
is an awesome package, however, it requires wrapping everything in a client side provider. And thus, it takes away all the benefits of Server Components.
react18-themes-lite
removes this limitation and enables you to unleash the full power of React 18 Server Components. In addition, more features are coming up soon... Stay tuned!
- ✅ Fully Treeshakable (
import from react18-themes-lite/client/component
) - ✅ Full TypeScript Support
- ✅ Unleash the full power of React18 Server components
- ✅ Works with all build systems/tools/frameworks for React18
- ✅ Perfect dark mode in 2 lines of code
- ✅ System setting with prefers-color-scheme
- ✅ Themed browser UI with color-scheme
- ✅ Support for Next.js 13
appDir
- ✅ Sync theme across tabs and windows
- ✅ Theme in sync with server component
- ✅ Disable flashing when changing themes
- ✅ Force pages to specific themes
- ✅ Class or data attribute selector
- ✅ Manipulate theme via
useTheme
hook
Check out the live example.
Install
$ pnpm add react18-themes-lite
# or
$ npm install react18-themes-lite
# or
$ yarn add react18-themes-lite
$ pnpm add react18-themes-lite-lite
# or
$ npm install react18-themes-lite-lite
# or
$ yarn add react18-themes-lite-lite
You need Zustand as a peer-dependency
Use
With pages/
The best way is to add a Custom App
to use by modifying _app
as follows:
Adding dark mode support takes 2 lines of code:
import { ThemeSwitcher } from "react18-themes-lite";
function MyApp({ Component, pageProps }) {
return (
<>
<ThemeSwitcher forcedTheme={Component.theme} />
<Component {...pageProps} />
</>
);
}
export default MyApp;
⚡🎉Boom! Just a couple of lines and your dark mode is ready!
Check out examples for advanced usage.
With app/
Update your app/layout.jsx
to add ThemeSwitcher
and ServerSideWrapper
from react18-themes-lite
. ServerSideWrapper
is required to avoid flash of un-themed content on reload.
// app/layout.jsx
import { ThemeSwitcher } from "react18-themes-lite";
import { ServerSideWrapper } from "react18-themes-lite/server/nextjs";
export default function Layout({ children }) {
return (
<ServerSideWrapper tag="html" lang="en">
<head />
<body>
<ThemeSwitcher />
{children}
</body>
</ServerSideWrapper>
);
}
Woohoo! You just added dark mode and you can also use Server Component! Isn't that awesome!
HTML & CSS
That's it, your Next.js app fully supports dark mode, including System preference with prefers-color-scheme
. The theme is also immediately synced between tabs. By default, react18-themes-lite modifies the data-theme
attribute on the html
element, which you can easily use to style your app:
:root {
/* Your default theme */
--background: white;
--foreground: black;
}
[data-theme="dark"] {
--background: black;
--foreground: white;
}
useTheme
In case your components need to know the current theme and be able to change it. The useTheme
hook provides theme information:
import { useTheme } from "react18-themes-lite";
const ThemeChanger = () => {
/* you can also improve performance by using selectors
* const [theme, setTheme] = useTheme(state => [state.theme, state.setTheme]);
*/
const { theme, setTheme } = useTheme();
return (
<div>
The current theme is: {theme}
<button onClick={() => setTheme("light")}>Light Mode</button>
<button onClick={() => setTheme("dark")}>Dark Mode</button>
</div>
);
};
Force per page theme and color-scheme
Next.js app router
import { ForceTheme } from "react18-themes-lite";
function MyPage() {
return (
<>
<ForceTheme theme={"my-theme"} />
...
</>
);
}
export default MyPage;
Next.js pages router
For pages router, you have 2 options. One is the same as the app router and the other option which is compatible with next-themes
is to add theme
to your page component as follows.
function MyPage() {
return <>...</>;
}
MyPage.theme = "my-theme";
export default MyPage;
In a similar way, you can also force color scheme.
Forcing color scheme will apply your defaultDark or defaultLight theme, configurable via hooks.
Migrating from v0 to v1
- defaultDarkTheme is renamed to darkTheme
- setDefaultDarkTheme is renamed to setDarkTheme
- defaultLightTheme is renamed to lightTheme
- setDefaultLightTheme is renamed to setLightTheme
Docs
🤩 Don't forger to start this repo!
Want handson course for getting started with Turborepo? Check out React and Next.js with TypeScript
License
Licensed as MIT open source.
with 💖 by Mayank Kumar Chaudhari