to add darkMode: 'class' to my tailwind.config.js,
to add class="dark" to the html-tag, and
to put dark: in front of any color, like so dark:bg-black
That works so far, but the user is not able to switch between dark and normal mode yet. Is there a way to remove/add class="dark" from/to the html-tag on server side in pure elixir with Lieview or has this to be done via JS?
// app.js
function darkExpected() {
return localStorage.theme === 'dark' || (!('theme' in localStorage) &&
window.matchMedia('(prefers-color-scheme: dark)').matches);
}
function initDarkMode() {
// On page load or when changing themes, best to add inline in `head` to avoid FOUC
if (darkExpected()) document.documentElement.classList.add('dark');
else document.documentElement.classList.remove('dark');
}
window.addEventListener("toogle-darkmode", e => {
if (darkExpected()) localStorage.theme = 'light';
else localStorage.theme = 'dark';
initDarkMode();
})
initDarkMode();
// trigger
// phx-click={JS.dispatch("toogle-darkmode")}
Just pointing up something that can help others: you should use color-scheme: dark; because it sets some CSS standards to dark color like inputs, scrollbars, and so on.
I know writing JS is not something Elixir devs can be fan of, but I think implementation of dark/light mode is elegant with the help of AlpineJS. Also in this case, JS is not interacting with server and dealing solely with client-side feature, that makes it even more appropriate to use it in this case instead of making round-trips to the server LiveView way
// assets/js/app.js:
function applyColorSchemePreference() {
const darkExpected = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (darkExpected) {
document.documentElement.classList.add('dark');
document.documentElement.style.setProperty('color-scheme', 'dark');
}
else {
document.documentElement.classList.remove('dark');
document.documentElement.style.setProperty('color-scheme', 'light');
}
}
// set listener to update color scheme preference on change
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
const newColorScheme = event.matches ? "dark" : "light";
console.log(newColorScheme);
applyColorSchemePreference();
});
// check color scheme preference on page load
applyColorSchemePreference();
This doesn’t allow for manual toggling: it defers to the operating system. But it toggles automatically whenever the operating system switches between dark & light modes.