A dev-only theme toggle for Next.js.
Switch light/dark mode with one key while building.
Run the initializer from a Next.js App Router project:
pnpm dlx nualt-theme-toggle initor:
npx nualt-theme-toggle initThen start your app:
pnpm devPress t to switch theme. Press Shift+H to hide or show the floating button.
Dark mode work should not require opening Chrome DevTools or changing your OS theme.
nualt-theme-toggle gives you a tiny dev-only control that forces html.light or html.dark, while keeping the system preference as the default state.
- installs
nualt-theme-toggleif it is missing - imports
nualt-theme-toggle/styles.css - renders
<ThemeToggle />inapp/layoutorsrc/app/layout - adds Tailwind v4 class-based dark mode support
- adds
:root.lightand:root.darkoverrides when the default Next theme variables are present - stays hidden from production by default
| Shortcut | Action |
|---|---|
t |
Toggle light/dark mode |
Shift+H |
Hide/show the floating button |
import { ThemeToggle } from "nualt-theme-toggle";
import "nualt-theme-toggle/styles.css";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<body>
{children}
<ThemeToggle />
</body>
</html>
);
}For Tailwind v4, your global CSS must include:
@custom-variant dark (&:where(.dark, .dark *));If your app uses the default Next variables from create-next-app, keep system mode as the default and add forced overrides:
:root.light {
--background: #ffffff;
--foreground: #171717;
}
:root.dark {
--background: #0a0a0a;
--foreground: #ededed;
}The init command handles this for the default Next template.
type ThemeToggleProps = {
buttonClassName?: string;
className?: string;
enabledInProduction?: boolean;
labels?: {
light?: string;
dark?: string;
};
shortcut?: string | false;
showFloatingButton?: boolean;
visibilityShortcut?: string | false;
};Defaults:
- dev-only
- shortcut:
t - visibility shortcut:
Shift+H - root classes:
html.light/html.dark - no localStorage persistence
- system preference stays active until you force a mode
- Next.js App Router
- React 18+
- Tailwind CSS v4
- class-based dark mode through
html.dark - CSS variables through
:root.lightand:root.dark
MIT
