@@ -2,7 +2,10 @@ import * as Base64 from "./base64.js";
22import { chroma } from "./chroma.js" ;
33
44function init ( ) {
5- const darkMode = window . matchMedia ?. ( "(prefers-color-scheme: dark)" ) . matches ;
5+ const systemDarkModeQuery = window . matchMedia ?. (
6+ "(prefers-color-scheme: dark)" ,
7+ ) ;
8+ const systemDarkMode = systemDarkModeQuery ?. matches ;
69 const style = document . createElement ( "style" ) ;
710 const ref = document . querySelector ( "script" ) ;
811 ref . parentNode . insertBefore ( style , ref ) ;
@@ -15,6 +18,82 @@ function init() {
1518 const csrfToken = form . elements [ "gorilla.csrf.Token" ] . value ;
1619 const output = document . getElementById ( "output" ) ;
1720 const htmlCheckbox = document . getElementById ( "html" ) ;
21+ const themeToggle = document . getElementById ( "theme-toggle" ) ;
22+ const themeIcon = document . getElementById ( "theme-icon" ) ;
23+
24+ function getThemePreference ( ) {
25+ const stored = localStorage . getItem ( "theme" ) ;
26+ if ( stored ) {
27+ return stored ;
28+ }
29+ return "auto" ;
30+ }
31+
32+ function setThemePreference ( theme ) {
33+ if ( theme === "auto" ) {
34+ localStorage . removeItem ( "theme" ) ;
35+ } else {
36+ localStorage . setItem ( "theme" , theme ) ;
37+ }
38+ }
39+
40+ function getEffectiveTheme ( theme ) {
41+ if ( theme === "auto" ) {
42+ const currentSystemDarkMode = systemDarkModeQuery ?. matches ?? false ;
43+ return currentSystemDarkMode ? "dark" : "light" ;
44+ }
45+ return theme ;
46+ }
47+
48+ function applyTheme ( theme ) {
49+ const effectiveTheme = getEffectiveTheme ( theme ) ;
50+ const isDark = effectiveTheme === "dark" ;
51+ document . documentElement . setAttribute ( "data-theme" , effectiveTheme ) ;
52+
53+ // Set icon based on the effective theme (current mode)
54+ if ( theme === "auto" ) {
55+ themeIcon . setAttribute ( "name" , "ellipse-outline" ) ;
56+ } else if ( isDark ) {
57+ themeIcon . setAttribute ( "name" , "moon-outline" ) ;
58+ } else {
59+ themeIcon . setAttribute ( "name" , "sunny-outline" ) ;
60+ }
61+
62+ if ( isDark && styleSelect . value === "monokailight" ) {
63+ styleSelect . value = "monokai" ;
64+ update ( new Event ( "change" ) ) ;
65+ } else if ( ! isDark && styleSelect . value === "monokai" ) {
66+ styleSelect . value = "monokailight" ;
67+ update ( new Event ( "change" ) ) ;
68+ }
69+ }
70+
71+ function toggleTheme ( ) {
72+ const currentTheme = getThemePreference ( ) ;
73+ let newTheme ;
74+ if ( currentTheme === "light" ) {
75+ newTheme = "dark" ;
76+ } else if ( currentTheme === "dark" ) {
77+ newTheme = "auto" ;
78+ } else {
79+ newTheme = "light" ;
80+ }
81+ setThemePreference ( newTheme ) ;
82+ applyTheme ( newTheme ) ;
83+ }
84+
85+ themeToggle . addEventListener ( "click" , toggleTheme ) ;
86+
87+ // Listen for system preference changes
88+ if ( systemDarkModeQuery ) {
89+ systemDarkModeQuery . addEventListener ( "change" , ( e ) => {
90+ const currentTheme = getThemePreference ( ) ;
91+ if ( currentTheme === "auto" ) {
92+ // Re-apply theme to update based on new system preference
93+ applyTheme ( "auto" ) ;
94+ }
95+ } ) ;
96+ }
1897
1998 ( document . querySelectorAll ( ".notification .delete" ) || [ ] ) . forEach ( ( el ) => {
2099 const notification = el . parentNode ;
@@ -183,6 +262,9 @@ function init() {
183262 event . preventDefault ( ) ;
184263 }
185264
265+ const initialTheme = getThemePreference ( ) ;
266+ applyTheme ( initialTheme ) ;
267+
186268 if ( location . hash ) {
187269 let json = Base64 . decode ( location . hash . substring ( 1 ) ) ;
188270 json = JSON . parse ( json ) ;
@@ -191,10 +273,12 @@ function init() {
191273 styleSelect . value = json . style ;
192274 htmlCheckbox . checked = json . classes ;
193275 update ( new Event ( "change" ) ) ;
194- } else if ( darkMode ) {
195- styleSelect . value = "monokai" ;
196- update ( new Event ( "change" ) ) ;
197276 } else {
277+ const effectiveTheme = getEffectiveTheme ( initialTheme ) ;
278+ const isDark = effectiveTheme === "dark" ;
279+ if ( isDark && styleSelect . value === "monokailight" ) {
280+ styleSelect . value = "monokai" ;
281+ }
198282 update ( new Event ( "change" ) ) ;
199283 }
200284
0 commit comments