simple-nextjs-darkmode
v1.0.6
Published
Simple, automatic dark mode for Next.Js
Downloads
15
Readme
simple-nextjs-darkmode
This package is targetted for Next.Js projects using shadcn/ui, but may work with other ui frameworks depending on their implementation.
Motivation
shadcn/ui
handles dark mode by applying the dark
class to some root element. I couldn't find a clean way to respect the user's system preference when using React Server Components, so I wrote this.
Features
- Automatic system preference detection
- Automatic live updates, no page reload required
- Simple installation and usage
- Stores preference per client in a cookie
- Planned: Callbacks for persistent storage per user
Installation
npm install --save simple-nextjs-darkmode
Usage
The package provides a DEFAULT_CLASS_NAME
constant (defaults to dark
from shadcn/ui
).
To override this, set the data-darkmode-class
attribute to the class you want to use on the element tagged with data-darkmode-target
.
<body data-darkmode-target data-darkmode-class="dark-theme"></body>
With React Server Components
React Server Components are the preferred way to use this package. Rendering dark mode on the server prevents a flash of light for dark mode users.
import { getServerDarkMode } from "simple-nextjs-darkmode/server";
import { DarkModeManager } from "simple-nextjs-darkmode/client";
import { DEFAULT_CLASS_NAME } from "simple-nextjs-darkmode/constants";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const darkMode = getServerDarkMode(); // Use this to get the dark mode state for the initial server-side render
return (
<html lang="en">
<body
className={darkMode ? DEFAULT_CLASS_NAME : ""}
data-darkmode-target
>
<DarkModeManager />
{children}
</body>
</html>
);
}
Without React Server Components
Without React Server Components, an additional flag is required to force the dark mode to be updated on the client. The user will see a flash of light mode for dark mode users. This is obviously less than ideal, but it works if you can't use Server Components for some reason.
"use client";
import {
getClientDarkMode,
DarkModeManager,
} from "simple-nextjs-darkmode/client";
export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
const darkMode = getClientDarkMode(); // Only necessary if you need to know the current dark mode state
return (
<html lang="en">
<body data-darkmode-target>
<DarkModeManager alwaysUpdate />
{children}
</body>
</html>
);
}
Updating the user preference
Allowing the user to change the dark mode preference is as simple as calling updateClientPreference
with the new preference.
"use client";
import {
getClientPreference,
updateUserPreference,
} from "simple-nextjs-darkmode/client";
export default function UpdatePreference() {
return (
<div>
<p>Current dark mode preference: {getClientPreference()}</p>
<button onClick={() => updateClientPreference("dark")}>
Dark Mode
</button>
<button onClick={() => updateClientPreference("light")}>
Light Mode
</button>
<button onClick={() => updateClientPreference("system")}>
System Preference
</button>
{children}
</div>
);
}
Issues
This is my first ever npm package, so I'm sure there's something I didn't do quite right. If you find any issues, please open an issue here or feel free to fix it yourself and submit a pull request.
Versioning
This package uses semver for versioning.