diff --git a/images/winter/grinch-smile-spritesheet.png b/images/winter/grinch-smile-spritesheet.png new file mode 100644 index 0000000..aba30f9 Binary files /dev/null and b/images/winter/grinch-smile-spritesheet.png differ diff --git a/src/theme.js b/src/theme.js index 26c3762..f9bdda1 100644 --- a/src/theme.js +++ b/src/theme.js @@ -3,13 +3,6 @@ const theme_storage_key = "jspaint theme"; const href_for = theme => `styles/themes/${theme}`; - let current_theme; - try { - current_theme = localStorage[theme_storage_key] || default_theme; - } catch (error) { - current_theme = default_theme; - } - let iid; function wait_for_theme_loaded(theme, callback) { clearInterval(iid); @@ -25,6 +18,24 @@ }, 15); } + let grinch_button; + let current_theme; + try { + const grinch = localStorage.grinch === "true"; + const is_december = new Date().getMonth() === 11; + if (is_december && !grinch) { + current_theme = "winter.css"; // overriding theme preference until you disable the seasonal theme + wait_for_theme_loaded(current_theme, () => { // could just wait for DOM to load, but theme is needed for the button styling + make_grinch_button(); + }); + } else { + current_theme = localStorage[theme_storage_key] || default_theme; + } + } catch (error) { + console.error(error); + current_theme = default_theme; + } + const theme_link = document.createElement("link"); theme_link.rel = "stylesheet"; theme_link.type = "text/css"; @@ -39,6 +50,8 @@ try { localStorage[theme_storage_key] = theme; + localStorage.grinch = "true"; // any theme change disables seasonal theme (unless of course you select the seasonal theme) + grinch_button?.remove(); // eslint-disable-next-line no-empty } catch(error) {} @@ -51,4 +64,25 @@ theme_link.href = href_for(theme); signal_theme_load(); }; + + function make_grinch_button() { + const button = document.createElement("button"); + button.ariaLabel = "Disable seasonal theme"; + button.className = "grinch-button"; + button.onclick = () => { + let new_theme; + try { + localStorage.grinch = "true"; + new_theme = localStorage[theme_storage_key] || default_theme; + // eslint-disable-next-line no-empty + } catch (error) { } + if (new_theme === "winter.css") { + new_theme = default_theme; + } + set_theme(new_theme); + button.remove(); + }; + document.body.appendChild(button); + grinch_button = button; + } })(); diff --git a/styles/themes/winter.css b/styles/themes/winter.css index fc5c952..7cba382 100644 --- a/styles/themes/winter.css +++ b/styles/themes/winter.css @@ -146,3 +146,28 @@ color: red; } } + +/* a button to leave the Winter theme */ +button.grinch-button { + position: absolute; + bottom: 0px; + right: 30px; + width: 100px; + height: 179px; + z-index: 2; + background-image: url("../../images/winter/grinch-smile-spritesheet.png"); + border: 0; + background-color: transparent; + cursor: pointer; +} +button.grinch-button:hover { + animation: grinch-smile 2s steps(37) forwards; +} +@keyframes grinch-smile { + from { + background-position: 0 0; + } + to { + background-position: -3700px 0; + } +}