Skip to content

Instantly share code, notes, and snippets.

@dbernheisel
Last active November 2, 2022 02:16
Show Gist options
  • Save dbernheisel/3658f66c433756435dad729095735b42 to your computer and use it in GitHub Desktop.
Save dbernheisel/3658f66c433756435dad729095735b42 to your computer and use it in GitHub Desktop.
Theme Chooser in Phoenix and JavaScript
// loaded with a <script> in <head> (not defer or async). Not async or deferred so that it
// executes before content is loaded to prevent flashing your light theme first before switching to dark.
// Works best with a class-based dark/light theme with Tailwind,
// in tailwind.config.js => darkMode: "class",
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)")
// colorScheme determines browser UI elements being light or dark
const colorScheme = document.head.querySelector("meta[name='color-scheme']")
// themeColor colors the browser chrome in some cases, like Google Chrome on mobile and Safari on desktop.
const themeColor = document.head.querySelector("meta[name='theme-color']")
const light = "#FFFFFF" // light background color
const dark = "#1F0E2B" // dark background color
window.currentTheme = () => window.localStorage.theme || "system"
window.darkMode = function() {
document.documentElement.classList.add("dark")
if(colorScheme) colorScheme.setAttribute("content", "dark")
if(themeColor) themeColor.setAttribute("content", dark)
}
window.lightMode = function() {
document.documentElement.classList.remove("dark")
if(colorScheme) colorScheme.setAttribute("content", "light")
if(themeColor) themeColor.setAttribute("content", light)
}
window.updateTheme = function(theme) {
switch(theme) {
case "light":
localStorage.theme = "light"
lightMode()
break;
case "dark":
localStorage.theme = "dark"
darkMode()
break;
default:
localStorage.removeItem("theme")
prefersDark.matches ? darkMode() : lightMode()
break;
}
}
prefersDark.addEventListener("change", e => {
if (localStorage.theme) return
e.matches ? darkMode() : lightMode()
});
updateTheme(localStorage.theme)
// loaded with a <script defer> in <head> so the DOM is present so it can find the element.
const el = document.getElementById("themeChooser")
if(el) {
const currentTheme = window.currentTheme()
const option = document.getElementById(`theme-${currentTheme}`)
if(option) { option.selected = currentTheme === option.value }
el.addEventListener("change", (e) => window.updateTheme(e.target.value))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment