dark mode
This commit is contained in:
parent
856c2e926b
commit
fbad8c64b2
3 changed files with 74 additions and 37 deletions
|
|
@ -96,7 +96,7 @@
|
|||
@custom-variant phx-submit-loading (.phx-submit-loading&, .phx-submit-loading &);
|
||||
@custom-variant phx-change-loading (.phx-change-loading&, .phx-change-loading &);
|
||||
|
||||
/* Use the data attribute for dark mode */
|
||||
/* Use the data attribute for dark mode */
|
||||
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));
|
||||
|
||||
/* Make LiveView wrapper divs transparent for layout */
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.nav_link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative flex items-center">
|
||||
<div class="relative flex items-center gap-2">
|
||||
<.theme_toggle />
|
||||
<button
|
||||
type="button"
|
||||
id="org-menu-button"
|
||||
|
|
@ -335,32 +336,50 @@ defmodule ToweropsWeb.Layouts do
|
|||
"""
|
||||
def theme_toggle(assigns) do
|
||||
~H"""
|
||||
<div class="card relative flex flex-row items-center border-2 border-base-300 bg-base-300 rounded-full">
|
||||
<div class="absolute w-1/3 h-full rounded-full border-1 border-base-200 bg-base-100 brightness-200 left-0 [[data-theme=light]_&]:left-1/3 [[data-theme=dark]_&]:left-2/3 transition-[left]" />
|
||||
|
||||
<div class="relative" id="theme-toggle" phx-update="ignore">
|
||||
<button
|
||||
class="flex p-2 cursor-pointer w-1/3"
|
||||
phx-click={JS.dispatch("phx:set-theme")}
|
||||
data-phx-theme="system"
|
||||
type="button"
|
||||
id="theme-menu-button"
|
||||
phx-click={JS.toggle(to: "#theme-menu")}
|
||||
class="flex items-center justify-center p-2 rounded-md text-zinc-500 hover:text-zinc-700 hover:bg-zinc-100 dark:text-zinc-400 dark:hover:text-zinc-200 dark:hover:bg-zinc-800"
|
||||
aria-label="Toggle theme"
|
||||
>
|
||||
<.icon name="hero-computer-desktop-micro" class="size-4 opacity-75 hover:opacity-100" />
|
||||
<.icon name="hero-sun" class="size-5 block dark:hidden" />
|
||||
<.icon name="hero-moon" class="size-5 hidden dark:block" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="flex p-2 cursor-pointer w-1/3"
|
||||
phx-click={JS.dispatch("phx:set-theme")}
|
||||
data-phx-theme="light"
|
||||
<div
|
||||
id="theme-menu"
|
||||
class="hidden absolute top-full right-0 mt-2 w-36 origin-top-right rounded-md bg-white shadow-lg ring-1 ring-black/5 z-50 dark:bg-zinc-800 dark:ring-white/10"
|
||||
phx-click-away={JS.hide(to: "#theme-menu")}
|
||||
>
|
||||
<.icon name="hero-sun-micro" class="size-4 opacity-75 hover:opacity-100" />
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="flex p-2 cursor-pointer w-1/3"
|
||||
phx-click={JS.dispatch("phx:set-theme")}
|
||||
data-phx-theme="dark"
|
||||
>
|
||||
<.icon name="hero-moon-micro" class="size-4 opacity-75 hover:opacity-100" />
|
||||
</button>
|
||||
<div class="py-1">
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="system"
|
||||
>
|
||||
<.icon name="hero-computer-desktop" class="size-4" /> Auto
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="light"
|
||||
>
|
||||
<.icon name="hero-sun" class="size-4" /> Light
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex w-full items-center gap-2 px-4 py-2 text-sm text-zinc-700 hover:bg-zinc-100 dark:text-zinc-300 dark:hover:bg-zinc-700"
|
||||
phx-click={JS.dispatch("phx:set-theme") |> JS.hide(to: "#theme-menu")}
|
||||
data-phx-theme="dark"
|
||||
>
|
||||
<.icon name="hero-moon" class="size-4" /> Dark
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
end
|
||||
|
|
@ -411,7 +430,8 @@ defmodule ToweropsWeb.Layouts do
|
|||
</.link>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center">
|
||||
<div class="flex items-center gap-2">
|
||||
<.theme_toggle />
|
||||
<.link
|
||||
navigate={~p"/orgs"}
|
||||
class="text-sm text-zinc-600 hover:text-zinc-900 dark:text-zinc-400 dark:hover:text-zinc-100"
|
||||
|
|
|
|||
|
|
@ -12,20 +12,37 @@
|
|||
</script>
|
||||
<script>
|
||||
(() => {
|
||||
const setTheme = (theme) => {
|
||||
if (theme === "system") {
|
||||
localStorage.removeItem("phx:theme");
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
} else {
|
||||
localStorage.setItem("phx:theme", theme);
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
}
|
||||
const mql = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
|
||||
const getSystemTheme = () => mql.matches ? "dark" : "light";
|
||||
|
||||
const applyTheme = () => {
|
||||
const preference = localStorage.getItem("phx:theme") || "system";
|
||||
const theme = preference === "system" ? getSystemTheme() : preference;
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
};
|
||||
if (!document.documentElement.hasAttribute("data-theme")) {
|
||||
setTheme(localStorage.getItem("phx:theme") || "system");
|
||||
}
|
||||
window.addEventListener("storage", (e) => e.key === "phx:theme" && setTheme(e.newValue || "system"));
|
||||
|
||||
|
||||
const setTheme = (preference) => {
|
||||
if (preference === "system") {
|
||||
localStorage.removeItem("phx:theme");
|
||||
} else {
|
||||
localStorage.setItem("phx:theme", preference);
|
||||
}
|
||||
applyTheme();
|
||||
};
|
||||
|
||||
// Apply theme on page load
|
||||
applyTheme();
|
||||
|
||||
// Listen for system preference changes (for auto mode)
|
||||
mql.addEventListener("change", applyTheme);
|
||||
|
||||
// Listen for storage changes from other tabs
|
||||
window.addEventListener("storage", (e) => {
|
||||
if (e.key === "phx:theme") applyTheme();
|
||||
});
|
||||
|
||||
// Listen for theme change events from LiveView
|
||||
window.addEventListener("phx:set-theme", (e) => setTheme(e.target.dataset.phxTheme));
|
||||
})();
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue