commit e9af99f3d799c1c25c22c082af54be2e02a0e344
parent 3b8310f7150a42b958b2a214c60bc9869712156f
Author: Hunter
Date:   Wed, 29 Jul 2026 16:44:59 -0400

smoothly transition colors when changing theme

Diffstat:
Mindex.html | 2+-
Mresources/style.css | 41++++++++++++++++++++++++++++++++++++++++-
Mresources/theme.js | 14++++++++++++--
3 files changed, 53 insertions(+), 4 deletions(-)

diff --git a/index.html b/index.html @@ -7,6 +7,7 @@ <title>memori</title> <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>✂️</text></svg>"> <link rel="stylesheet" href="resources/style.css"> + <script src="resources/theme.js"></script> </head> <body> <div class="page"> @@ -25,7 +26,6 @@ <script src="resources/pointer.js"></script> <script src="resources/input.js"></script> <script src="resources/print.js"></script> - <script src="resources/theme.js"></script> <script src="resources/app.js"></script> <script src="resources/pdf.js"></script> </body> diff --git a/resources/style.css b/resources/style.css @@ -1,3 +1,29 @@ +/* Registered so theme swaps can be transitioned — plain custom properties don't animate. + Everything downstream (borders, color-mix, scrollbars) follows for free. */ +@property --desk { + syntax: '<color>'; + inherits: true; + initial-value: #7a8520; +} + +@property --page { + syntax: '<color>'; + inherits: true; + initial-value: #fefef4; +} + +@property --grid-line { + syntax: '<color>'; + inherits: true; + initial-value: #a9cf51; +} + +@property --accent { + syntax: '<color>'; + inherits: true; + initial-value: #a81d8f; +} + :root { /* Default colors */ --white: white; @@ -69,6 +95,19 @@ /* Set font */ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; + + --theme-transition: 250ms ease; + transition: + --desk var(--theme-transition), + --page var(--theme-transition), + --grid-line var(--theme-transition), + --accent var(--theme-transition); +} + +@media (prefers-reduced-motion: reduce) { + :root { + transition: none; + } } /* Theme definitions */ @@ -626,7 +665,7 @@ body.selecting .image-container { -webkit-tap-highlight-color: transparent; user-select: none; -webkit-user-select: none; - transition: transform 0.1s ease, box-shadow 0.1s ease; + transition: transform 0.1s ease, box-shadow 0.1s ease, color var(--theme-transition); } .add-images-btn:active { diff --git a/resources/theme.js b/resources/theme.js @@ -5,12 +5,22 @@ const themes = ['sea-breeze', 'grape-soda', 'grapefruit', 'guac', 'mojito', 'ban const DEFAULT_THEME = 'guac'; const DEFAULT_DARK_THEME = 'pantry'; -function setTheme(theme) { - document.documentElement.setAttribute('data-theme', theme); +function syncThemeColorMeta() { const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--desk').trim(); document.querySelector('meta[name="theme-color"]').setAttribute('content', backgroundColor); } +function setTheme(theme) { + document.documentElement.setAttribute('data-theme', theme); + syncThemeColorMeta(); +} + +document.documentElement.addEventListener('transitionend', (e) => { + if (e.propertyName === '--desk') { + syncThemeColorMeta(); + } +}); + function cycleTheme() { currentThemeIndex = (currentThemeIndex + 1) % themes.length; const newTheme = themes[currentThemeIndex];