Created
November 22, 2024 16:56
-
-
Save frankdugan3/b3f5931049f330b81a3194036cb48a98 to your computer and use it in GitHub Desktop.
Simple, Robust Dark Mode for Phoenix & Tailwind v4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@variant dark (&:where([data-color-scheme^="dark"], [data-color-scheme^="dark"] *)); | |
@variant color-scheme-system (&:where([data-color-scheme*="-system"], [data-color-scheme*="-system"] *)); | |
@variant color-scheme-dark (&:where([data-color-scheme="dark"], [data-color-scheme="dark"] *)); | |
@variant color-scheme-light (&:where([data-color-scheme="light"], [data-color-scheme="light"] *)); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@doc """ | |
Button to switch dark/light/system color scheme | |
""" | |
def color_scheme_switcher(assigns) do | |
~H""" | |
<.button phx-click={JS.dispatch("toggle-color-scheme")} aria-label="toggle color scheme"> | |
<.icon | |
name="hero-computer-desktop" | |
class="hidden color-scheme-system:inline-block" | |
aria-label="system selected" | |
/> | |
<.icon | |
name="hero-moon" | |
class="hidden color-scheme-dark:inline-block" | |
aria-label="dark selected" | |
/> | |
<.icon | |
name="hero-sun" | |
class="hidden color-scheme-light:inline-block" | |
aria-label="light selected" | |
/> | |
</.button> | |
""" | |
end | |
@doc """ | |
Javascript to manage switching color schemes with `color_scheme_switcher/1`. | |
> #### Note: {: .info} | |
> | |
> This needs to be added in the page's head before `app.js` to prevent FOUC: | |
```heex | |
<%# root.html.heex %> | |
<head> | |
<.color_scheme_switcher_js /> | |
<script defer phx-track-static type="text/javascript" src={~p"/assets/app.js"}> | |
</head> | |
``` | |
""" | |
def color_scheme_switcher_js(assigns) do | |
~H""" | |
<script> | |
window.applyColorScheme = function (scheme) { | |
if (scheme === "system") { | |
if (window.matchMedia("(prefers-color-scheme: dark)").matches) { | |
document.documentElement.setAttribute("data-color-scheme", "dark-system"); | |
} else { | |
document.documentElement.setAttribute("data-color-scheme", "light-system"); | |
} | |
} else { | |
document.documentElement.setAttribute("data-color-scheme", scheme); | |
} | |
localStorage.scheme = scheme; | |
}; | |
window.toggleColorScheme = function () { | |
switch (localStorage.scheme) { | |
case "system": applyColorScheme("dark"); break; | |
case "dark": applyColorScheme("light"); break; | |
default: applyColorScheme("system"); | |
} | |
}; | |
// Initialize | |
applyColorScheme(localStorage.scheme || "system"); | |
// Watch preferred scheme | |
window | |
.matchMedia("(prefers-color-scheme: dark)") | |
.addEventListener("change", (_) => { | |
if (localStorage.scheme === "system") { | |
applyColorScheme("system"); | |
} | |
}); | |
// Watch changes made from different tab/window/browser | |
window.addEventListener("storage", (_) => applyColorScheme(localStorage.scheme)); | |
// Listen for toggle events | |
window.addEventListener("toggle-color-scheme", (_) => toggleColorScheme()); | |
</script> | |
""" | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment