From 425d00529e28c8102cd0d279da13bec9652d3020 Mon Sep 17 00:00:00 2001 From: Florian Schroedl Date: Thu, 5 Mar 2026 13:16:07 +0100 Subject: [PATCH] fix: disable CSS transitions during dark/light theme toggle Add a `[data-no-transitions]` CSS rule that suppresses all transitions. The theme toggle in all three dev targets (hiccup, replicant, squint) sets this attribute before switching, then removes it on the next animation frame, preventing the jarring animated color shift. --- dev/hiccup/src/dev/hiccup.clj | 2 +- dev/replicant/src/dev/replicant.cljs | 5 ++++- dev/squint/src/dev/squint.cljs | 5 ++++- src/ui/css/gen.clj | 6 ++++++ src/ui/dialog.css | 2 +- 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/dev/hiccup/src/dev/hiccup.clj b/dev/hiccup/src/dev/hiccup.clj index d76efbf..63a232e 100644 --- a/dev/hiccup/src/dev/hiccup.clj +++ b/dev/hiccup/src/dev/hiccup.clj @@ -362,7 +362,7 @@ (sidebar/sidebar-menu {} (sidebar/sidebar-menu-item {:icon-name :sun - :attrs {:onclick "document.documentElement.dataset.theme = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'"}} + :attrs {:onclick "document.documentElement.dataset.noTransitions = ''; document.documentElement.dataset.theme = document.documentElement.dataset.theme === 'dark' ? 'light' : 'dark'; requestAnimationFrame(() => { delete document.documentElement.dataset.noTransitions; })"}} "Toggle Dark Mode")))) (sidebar/sidebar-footer {} (sidebar/sidebar-user {:user-name "Dev Mode" :email (str "hiccup · port " own-port) :avatar "bb"})))) diff --git a/dev/replicant/src/dev/replicant.cljs b/dev/replicant/src/dev/replicant.cljs index b222e4c..4fc2efa 100644 --- a/dev/replicant/src/dev/replicant.cljs +++ b/dev/replicant/src/dev/replicant.cljs @@ -338,8 +338,11 @@ (defn toggle-theme! [_e] (let [el (.-documentElement js/document) current (.. el -dataset -theme)] + (set! (.. el -dataset -noTransitions) "") (set! (.. el -dataset -theme) - (if (= current "dark") "light" "dark")))) + (if (= current "dark") "light" "dark")) + (js/requestAnimationFrame + #(js-delete (.-dataset el) "noTransitions")))) ;; ── App Shell ─────────────────────────────────────────────────────── diff --git a/dev/squint/src/dev/squint.cljs b/dev/squint/src/dev/squint.cljs index 2f1d1b2..618d212 100644 --- a/dev/squint/src/dev/squint.cljs +++ b/dev/squint/src/dev/squint.cljs @@ -27,8 +27,11 @@ (defn toggle-theme! [_e] (let [el (.-documentElement js/document) current (.. el -dataset -theme)] + (set! (.. el -dataset -noTransitions) "") (set! (.. el -dataset -theme) - (if (= current "dark") "light" "dark")))) + (if (= current "dark") "light" "dark")) + (js/requestAnimationFrame + #(js-delete (.-dataset el) "noTransitions")))) (defn section [title & children] [:section {:style {"margin-bottom" "2.5rem"}} diff --git a/src/ui/css/gen.clj b/src/ui/css/gen.clj index b713f7a..57e8ee7 100644 --- a/src/ui/css/gen.clj +++ b/src/ui/css/gen.clj @@ -74,6 +74,12 @@ :focus:not(:focus-visible) { outline: none; box-shadow: none; +} + +[data-no-transitions] *, +[data-no-transitions] *::before, +[data-no-transitions] *::after { + transition: none !important; }") (defn collect-component-css diff --git a/src/ui/dialog.css b/src/ui/dialog.css index 7106a96..a9b0d32 100644 --- a/src/ui/dialog.css +++ b/src/ui/dialog.css @@ -6,7 +6,7 @@ max-height: 85vh; margin: auto; padding: 0; - background: var(--bg-1); + background: var(--bg-0); color: var(--fg-0); border: var(--border-0); border-radius: var(--radius-lg);