smoothly transition colors when changing theme
Hunter
Wednesday, July 29th, 2026 at 4:44 PM
7 <title>memori</title>
8 <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>">
9 <link rel="stylesheet" href="resources/style.css">
10 + <script src="resources/theme.js"></script>
11 </head>
12 <body>
13 <div class="page">
26 <script src="resources/pointer.js"></script>
27 <script src="resources/input.js"></script>
28 <script src="resources/print.js"></script>
- <script src="resources/theme.js"></script>
29 <script src="resources/app.js"></script>
30 <script src="resources/pdf.js"></script>
31 </body>
1 +/* Registered so theme swaps can be transitioned — plain custom properties don't animate.
2 + Everything downstream (borders, color-mix, scrollbars) follows for free. */
3 +@property --desk {
4 + syntax: '<color>';
5 + inherits: true;
6 + initial-value: #7a8520;
7 +}
8 +
9 +@property --page {
10 + syntax: '<color>';
11 + inherits: true;
12 + initial-value: #fefef4;
13 +}
14 +
15 +@property --grid-line {
16 + syntax: '<color>';
17 + inherits: true;
18 + initial-value: #a9cf51;
19 +}
20 +
21 +@property --accent {
22 + syntax: '<color>';
23 + inherits: true;
24 + initial-value: #a81d8f;
25 +}
26 +
27 :root {
28 /* Default colors */
29 --white: white;
95
96 /* Set font */
97 font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
98 +
99 + --theme-transition: 250ms ease;
100 + transition:
101 + --desk var(--theme-transition),
102 + --page var(--theme-transition),
103 + --grid-line var(--theme-transition),
104 + --accent var(--theme-transition);
105 +}
106 +
107 +@media (prefers-reduced-motion: reduce) {
108 + :root {
109 + transition: none;
110 + }
111 }
112
113 /* Theme definitions */
665 -webkit-tap-highlight-color: transparent;
666 user-select: none;
667 -webkit-user-select: none;
- transition: transform 0.1s ease, box-shadow 0.1s ease;
668 + transition: transform 0.1s ease, box-shadow 0.1s ease, color var(--theme-transition);
669 }
670
671 .add-images-btn:active {
5 const DEFAULT_THEME = 'guac';
6 const DEFAULT_DARK_THEME = 'pantry';
7
-function setTheme(theme) {
- document.documentElement.setAttribute('data-theme', theme);
8 +function syncThemeColorMeta() {
9 const backgroundColor = getComputedStyle(document.documentElement).getPropertyValue('--desk').trim();
10 document.querySelector('meta[name="theme-color"]').setAttribute('content', backgroundColor);
11 }
12
13 +function setTheme(theme) {
14 + document.documentElement.setAttribute('data-theme', theme);
15 + syncThemeColorMeta();
16 +}
17 +
18 +document.documentElement.addEventListener('transitionend', (e) => {
19 + if (e.propertyName === '--desk') {
20 + syncThemeColorMeta();
21 + }
22 +});
23 +
24 function cycleTheme() {
25 currentThemeIndex = (currentThemeIndex + 1) % themes.length;
26 const newTheme = themes[currentThemeIndex];