1.0.6 • Published 1 year ago

simple-nextjs-darkmode v1.0.6

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

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.

1.0.6

1 year ago

1.0.5

1 year ago

1.0.4

1 year ago

1.0.3

1 year ago

1.0.2

1 year ago

1.0.1

1 year ago

1.0.0

1 year ago