Skip to content

Instantly share code, notes, and snippets.

@frankdugan3
Created November 22, 2024 16:56
Show Gist options
  • Save frankdugan3/b3f5931049f330b81a3194036cb48a98 to your computer and use it in GitHub Desktop.
Save frankdugan3/b3f5931049f330b81a3194036cb48a98 to your computer and use it in GitHub Desktop.
Simple, Robust Dark Mode for Phoenix & Tailwind v4
@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"] *));
@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