A framework-agnostic, zero-dependency, and hyper-fast theme toggling library.
Perfect for everything from plain HTML sites to complex SSR React, Next.js, and Nuxt.js apps.
When it comes to dark mode toggling, developers usually face memory leaks in SPAs, hydration mismatches in Next.js/Nuxt.js, and annoying layout shifts.
DayniteJs solves all of this out of the box.
- 🚫 Zero Dependencies: Pure Vanilla Javascript.
- 💨 Lightweight: Extremely small bundle size (~1KB minified).
- 🧠 Smart Memory Management: Comes with robust cleanup mechanisms making it 100% leak-free for SPAs.
- 🛡️ Built-in Security: Hardened against
localStoragepoisoning. - 🌍 Universal Modules: Out of the box ESM, CommonJS, and UMD support for browsers.
- 🧲 Full TypeScript Support: Written with complete
.d.tstypes for rich IDE IntelliSense.
Drop this into your HTML <head> or before the closing </body> tag:
<!-- Load Daynite.js automagically! -->
<script type="module" src="https://unpkg.com/daynitejs/dist/daynitejs.esm.js" data-daynitejs-auto></script>
<!-- Use a button to toggle -->
<button onclick="window.daynite.toggle()">Toggle Theme</button>Install it inside your project:
npm install daynitejspnpm install daynitejsInitialize your theme in your app entry (e.g., main.js, _app.js, App.vue or useEffect):
import DayniteJs from 'daynitejs';
// Initialize the magic 🪄
const daynite = new DayniteJs({
themes: ['light', 'dark'],
defaultTheme: 'light',
customStyles: {
light: { '--bg-color': '#ffffff', '--text-color': '#1f2937' },
dark: { '--bg-color': '#1f2937', '--text-color': '#f3f4f6' }
}
});
// Toggle anywhere in your app:
daynite.toggle();DayniteJs is 100% hydration-safe and SSR-compatible.
import { useEffect, useState } from 'react';
import DayniteJs from 'daynitejs';
export default function ThemeToggler() {
const [daynite, setDaynite] = useState<DayniteJs | null>(null);
useEffect(() => {
// 1. Initialize client-side
const instance = new DayniteJs();
setDaynite(instance);
// 2. Prevent memory leaks on unmount
return () => instance.destroy();
}, []);
return (
<button onClick={() => daynite?.toggle()}>
Toggle Theme
</button>
);
}new DayniteJs(options)
Accepts a configuration object to change defaults.
{
themes?: string[]; // e.g. ['light', 'dark', 'dim']
defaultTheme?: string; // fallback theme
storageKey?: string; // localStorage custom key
customStyles?: Record<string, object>; // bind CSS vars to specific themes
}daynite.toggle()
Cycles dynamically to the next installed theme in the array.
daynite.setTheme(theme)
Explicitly switch to a specified theme name (e.g. daynite.setTheme('dark')).
daynite.getTheme()
Returns the string name of the currently active theme.
daynite.reset()
Resets the theme layout to follow the system preference (detects prefers-color-scheme).
daynite.onThemeChange(callback)
Subscribes to theme changes. Returns an unsubscribe function to help prevent memory leaks.
const unsubscribe = daynite.onThemeChange((activeTheme) => {
console.log('User swapped to:', activeTheme);
});
// Call unsubscribe() when component unmountsdaynite.destroy()
Removes all system event listeners and forcefully unbinds functions from memory. Essential for routing in SPA frameworks.
Q: I get "ReferenceError: document is not defined"
A: Initialize DayniteJs dynamically inside a client-side hook (like `useEffect` or Vue's `onMounted`), or conditionally check `typeof window !== 'undefined'` before initializing.
Q: Does DayniteJs work with Tailwind CSS?
A: Yes! DayniteJs appends a `dark` class globally on the `` root specifically mapped to support Tailwind CSS `darkMode: 'class'` configuration effortlessly.
Q: My custom CSS styles aren't appearing!
A: Make sure you define them inside the `customStyles` configuration during instantiation and verify that your CSS utilizes `var(--your-variable)` correctly.
We actively welcome contributions to grow DayniteJs!
- Read our Contributing Guidelines to get started.
- Please observe our Code of Conduct.
- If you find a bug, please create a Bug Report.
- Have an idea? Open a Feature Request.
MIT Copyright (c) Suhaib Muhammad Babangida.