theme.js (2.3 KB)
1 // Theme system 2 let currentThemeIndex = 0; 3 let isF2Pressed = false; 4 const themes = ['sea-breeze', 'grape-soda', 'grapefruit', 'guac', 'mojito', 'banana', 'pantry']; 5 const DEFAULT_THEME = 'guac'; 6 const DEFAULT_DARK_THEME = 'pantry'; 7 const THEME_TRANSITION_MS = parseFloat(getComputedStyle(document.documentElement).getPropertyValue('--theme-transition')); 8 let themeTransitionTimer = null; 9 10 function syncThemeColorMeta() { 11 const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--desk').trim(); 12 document.querySelector('meta[name="theme-color"]').setAttribute('content', backgroundColor); 13 } 14 15 function setTheme(theme) { 16 document.documentElement.setAttribute('data-theme', theme); 17 syncThemeColorMeta(); 18 } 19 20 function armPageRadiusTransition() { 21 const page = document.querySelector('.page'); 22 if (!page) return; 23 24 page.classList.add('theming'); 25 clearTimeout(themeTransitionTimer); 26 themeTransitionTimer = setTimeout(() => page.classList.remove('theming'), THEME_TRANSITION_MS + 50); 27 } 28 29 function cycleTheme(step = 1) { 30 currentThemeIndex = (currentThemeIndex + step + themes.length) % themes.length; 31 const newTheme = themes[currentThemeIndex]; 32 armPageRadiusTransition(); 33 setTheme(newTheme); 34 saveThemeToLocalStorage(newTheme); 35 } 36 37 function saveThemeToLocalStorage(theme) { 38 localStorage.setItem('memori-theme', theme); 39 } 40 41 function loadThemeFromLocalStorage() { 42 const savedTheme = localStorage.getItem('memori-theme'); 43 const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; 44 const theme = (savedTheme && themes.includes(savedTheme)) 45 ? savedTheme 46 : (prefersDark ? DEFAULT_DARK_THEME : DEFAULT_THEME); 47 48 currentThemeIndex = themes.indexOf(theme); 49 50 // the document opens on the default theme, so the first swap needs to land unanimated 51 document.documentElement.classList.add('no-theme-transition'); 52 setTheme(theme); 53 document.documentElement.offsetWidth; // flush the change before transitions come back 54 document.documentElement.classList.remove('no-theme-transition'); 55 } 56 57 // F2 cycles themes, shift+F2 cycles backwards 58 document.addEventListener('keydown', (e) => { 59 if (e.key === 'F2' && !isF2Pressed) { 60 e.preventDefault(); 61 isF2Pressed = true; 62 cycleTheme(e.shiftKey ? -1 : 1); 63 } 64 }); 65 66 document.addEventListener('keyup', (e) => { 67 if (e.key === 'F2') { 68 isF2Pressed = false; 69 } 70 }); 71 72 // Load theme on page load 73 loadThemeFromLocalStorage();