Skip to content

Commit f4a7b04

Browse files
committed
fix: dark mode flickering
Fixed by setting the preference in a cookie and load it from the server
1 parent c5b9cd6 commit f4a7b04

File tree

5 files changed

+44
-27
lines changed

5 files changed

+44
-27
lines changed
Lines changed: 19 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,18 @@
1-
const localStorageKey = "theme";
1+
const themeCookieKey = "theme";
22

33
const isDark = () => {
4-
if (localStorage.getItem(localStorageKey) === "dark") return true;
5-
if (localStorage.getItem(localStorageKey) === "light")
6-
return false;
7-
return window.matchMedia("(prefers-color-scheme: dark)").matches;
4+
const theme = document.cookie
5+
.split("; ")
6+
.find((row) => row.startsWith(`${themeCookieKey}=`))
7+
?.split("=")[1];
8+
return (
9+
theme == "dark" ||
10+
window.matchMedia("(prefers-color-scheme: dark)").matches
11+
);
12+
};
13+
14+
const setThemeCookie = (theme) => {
15+
document.cookie = `${themeCookieKey}=${theme}; path=/; max-age=31536000; SameSite=Strict;`; // would expire in a yer
816
};
917

1018
const setupThemeToggle = () => {
@@ -15,32 +23,19 @@ const setupThemeToggle = () => {
1523
const themeToggleLightIcon = document.getElementById(
1624
"theme-toggle-light-icon"
1725
);
18-
if (
19-
themeToggleDarkIcon == null ||
20-
themeToggleLightIcon == null
21-
)
22-
return;
23-
const show = dark
24-
? themeToggleDarkIcon
25-
: themeToggleLightIcon;
26-
const hide = dark
27-
? themeToggleLightIcon
28-
: themeToggleDarkIcon;
26+
if (themeToggleDarkIcon == null || themeToggleLightIcon == null) return;
27+
const show = dark ? themeToggleDarkIcon : themeToggleLightIcon;
28+
const hide = dark ? themeToggleLightIcon : themeToggleDarkIcon;
2929
show.classList.remove("hidden", "text-transparent");
3030
hide.classList.add("hidden", "text-transparent");
3131
if (dark) {
3232
document.documentElement.classList.add("dark");
33+
setThemeCookie("dark");
3334
} else {
3435
document.documentElement.classList.remove("dark");
36+
setThemeCookie("light");
3537
}
36-
try {
37-
localStorage.setItem(
38-
localStorageKey,
39-
dark ? "dark" : "light"
40-
);
41-
} catch (_err) {}
4238
};
43-
toggleVisibility(isDark());
4439
document
4540
.getElementById("theme-toggle")
4641
.addEventListener("click", function () {
@@ -52,7 +47,7 @@ const darkModeHook = {
5247
mounted() {
5348
setupThemeToggle();
5449
},
55-
updated() {}
50+
updated() {},
5651
};
5752

5853
export default darkModeHook;

explorer/lib/explorer_web/components/layouts/root.html.heex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!DOCTYPE html>
2-
<html lang="en" class="dark [scrollbar-gutter:stable]">
2+
<html lang="en" class={"#{@theme} [scrollbar-gutter:stable]"}>
33
<head>
44
<meta charset="utf-8" />
55
<meta name="viewport" content="width=device-width, initial-scale=1" />
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,15 @@
1-
defmodule ExplorerWeb.HostHook do
1+
defmodule ExplorerWeb.Hooks do
22
def on_mount(:add_host, _params, _session, socket) do
33
%URI{host: host} = Phoenix.LiveView.get_connect_info(socket, :uri)
44

55
socket = Phoenix.Component.assign(socket, host: host)
66

77
{:cont, socket}
88
end
9+
10+
def on_mount(:add_theme, _params, session, socket) do
11+
socket = Phoenix.Component.assign(socket, theme: session["theme"])
12+
13+
{:cont, socket}
14+
end
915
end

explorer/lib/explorer_web/plugs.ex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
defmodule ExplorerWeb.Plugs do
2+
import Plug.Conn
3+
4+
def init(default), do: default
5+
6+
def load_theme_cookie_in_session(conn, _opts) do
7+
# Default to dark if not present
8+
theme = Map.get(conn.cookies, "theme", "dark")
9+
10+
conn
11+
|> put_session(:theme, theme)
12+
end
13+
end

explorer/lib/explorer_web/router.ex

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule ExplorerWeb.Router do
22
use ExplorerWeb, :router
3+
import ExplorerWeb.Plugs
34

45
# https://furlough.merecomplexities.com/elixir/phoenix/security/2021/02/26/content-security-policy-configuration-in-phoenix.html
56

@@ -21,6 +22,7 @@ defmodule ExplorerWeb.Router do
2122
plug :accepts, ["html"]
2223
plug :fetch_session
2324
plug :fetch_live_flash
25+
plug :load_theme_cookie_in_session
2426
plug :put_root_layout, html: {ExplorerWeb.Layouts, :root}
2527
plug :protect_from_forgery
2628
plug :put_secure_browser_headers, %{"content-security-policy" => @content_security_policy}
@@ -34,7 +36,8 @@ defmodule ExplorerWeb.Router do
3436
pipe_through :browser
3537

3638
# https://fly.io/phoenix-files/live-session/
37-
live_session :default, on_mount: [{ExplorerWeb.HostHook, :add_host}] do
39+
live_session :default,
40+
on_mount: [{ExplorerWeb.Hooks, :add_host}, {ExplorerWeb.Hooks, :add_theme}] do
3841
live "/", Home.Index
3942
live "/batches/:merkle_root", Batch.Index
4043
live "/batches", Batches.Index

0 commit comments

Comments
 (0)