theme-change
theme-change copied to clipboard
Fixing toggle function
Hi, the themeToggle() function have some problems. It is creating a new eventlistener each time that the toggle is clicked and in vue isn't working (I'm trying with https://daisyui.com/)
This is a suggestion to fix (this code: https://github.com/saadeghi/theme-change/blob/master/src/toggle.js):
function themeToggle() {
const toggleEl = document.querySelector("[data-toggle-theme]");
const dataKey = toggleEl?.getAttribute("data-key") || "theme";
const currentTheme = localStorage.getItem(dataKey);
function setTheme(theme) {
document.documentElement.setAttribute("data-theme", theme);
document.querySelectorAll("[data-toggle-theme]").forEach((el) => {
el.classList.toggle(el.getAttribute("data-act-class"), theme !== null);
});
if (theme === null) {
localStorage.removeItem(dataKey);
} else {
localStorage.setItem(dataKey, theme);
}
}
if (currentTheme) {
setTheme(currentTheme);
}
if (toggleEl) {
toggleEl.addEventListener("click", function () {
const themesList = toggleEl.getAttribute("data-toggle-theme");
if (themesList) {
const themesArray = themesList.split(",");
const currentThemeIndex = themesArray.indexOf(
document.documentElement.getAttribute("data-theme")
);
const newThemeIndex = (currentThemeIndex + 1) % themesArray.length;
setTheme(themesArray[newThemeIndex]);
}
});
}
}
In vue, I make works with:
<template>
<input ref="themeToggle" data-toggle-theme="light,dark" data-act-class="ACTIVECLASS" type="checkbox"
class="toggle" />
</template>
<script setup lang='ts'>
import { onMounted, ref } from 'vue'
import { themeChange } from 'theme-change'
const themeToggle = ref(null);
const setTheme = (theme, dataKey) => {
document.documentElement.setAttribute('data-theme', theme);
document.querySelectorAll('[data-toggle-theme]').forEach((el) => {
el.classList.toggle(el.getAttribute('data-act-class'), theme !== null);
});
if (theme === null) {
localStorage.removeItem(dataKey);
} else {
localStorage.setItem(dataKey, theme);
}
};
onMounted(() => {
themeChange(false)
const toggleEl = themeToggle.value;
const dataKey = toggleEl.getAttribute('data-key') || 'theme';
const currentTheme = localStorage.getItem(dataKey);
if (currentTheme) {
setTheme(currentTheme, dataKey);
}
toggleEl.addEventListener('click', () => {
const themesList = toggleEl.getAttribute('data-toggle-theme');
if (themesList) {
const themesArray = themesList.split(',');
const currentThemeIndex = themesArray.indexOf(
document.documentElement.getAttribute('data-theme')
);
const newThemeIndex = (currentThemeIndex + 1) % themesArray.length;
setTheme(themesArray[newThemeIndex], dataKey);
}
});
});
</script>
I also have the issue in React. It works nicely just after set up, but when restarting the local server it fails to update the theme. Here's my code:
tailwind.config.js
module.exports = {
content: [
"./src/**/*.{js,jsx,ts,tsx}",
],
theme: {
[...]
},
daisyui: {
themes: [
"dark",
"light"
],
},
plugins: [require("daisyui")],
}
index.html
<!DOCTYPE html>
<html lang="en" data-theme="light">
[...]
</html>
Toggle Component
import { useEffect } from "react";
import { themeChange } from "theme-change";
const ThemeSwitch = () => {
useEffect(() => {
themeChange(false)
}, [])
return (
<div className="p-2">
<label className="swap swap-rotate">
<input type="checkbox" data-toggle-theme="light,dark"/>
<svg className="swap-on fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M5.64,17l-.71.71a1,1,0,0,0,0,1.41,1,1,0,0,0,1.41,0l.71-.71A1,1,0,0,0,5.64,17ZM5,12a1,1,0,0,0-1-1H3a1,1,0,0,0,0,2H4A1,1,0,0,0,5,12Zm7-7a1,1,0,0,0,1-1V3a1,1,0,0,0-2,0V4A1,1,0,0,0,12,5ZM5.64,7.05a1,1,0,0,0,.7.29,1,1,0,0,0,.71-.29,1,1,0,0,0,0-1.41l-.71-.71A1,1,0,0,0,4.93,6.34Zm12,.29a1,1,0,0,0,.7-.29l.71-.71a1,1,0,1,0-1.41-1.41L17,5.64a1,1,0,0,0,0,1.41A1,1,0,0,0,17.66,7.34ZM21,11H20a1,1,0,0,0,0,2h1a1,1,0,0,0,0-2Zm-9,8a1,1,0,0,0-1,1v1a1,1,0,0,0,2,0V20A1,1,0,0,0,12,19ZM18.36,17A1,1,0,0,0,17,18.36l.71.71a1,1,0,0,0,1.41,0,1,1,0,0,0,0-1.41ZM12,6.5A5.5,5.5,0,1,0,17.5,12,5.51,5.51,0,0,0,12,6.5Zm0,9A3.5,3.5,0,1,1,15.5,12,3.5,3.5,0,0,1,12,15.5Z"/></svg>
<svg className="swap-off fill-current w-8 h-8" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M21.64,13a1,1,0,0,0-1.05-.14,8.05,8.05,0,0,1-3.37.73A8.15,8.15,0,0,1,9.08,5.49a8.59,8.59,0,0,1,.25-2A1,1,0,0,0,8,2.36,10.14,10.14,0,1,0,22,14.05,1,1,0,0,0,21.64,13Zm-9.5,6.69A8.14,8.14,0,0,1,7.08,5.22v.27A10.15,10.15,0,0,0,17.22,15.63a9.79,9.79,0,0,0,2.1-.22A8.11,8.11,0,0,1,12.14,19.73Z"/></svg>
</label>
</div>
);
};
export default ThemeSwitch;
Working with React 18
I have the same problem that @guschiavon on react...
Me too, I use next.js and facing the same issue :(
Me too, with Next 14 and React 18
Same issue, using Next, React, and DaisyUI