From d02c19dbd9098a0ce032a7ef21c4f93b255c3709 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 11:03:08 +0200 Subject: [PATCH 01/16] format html also --- index.html | 205 ++++++++++++++++------- public/assets/ui-svgs/dark-mode-moon.svg | 1 + public/assets/ui-svgs/dark-mode-sun.svg | 1 + 3 files changed, 142 insertions(+), 65 deletions(-) create mode 100644 public/assets/ui-svgs/dark-mode-moon.svg create mode 100644 public/assets/ui-svgs/dark-mode-sun.svg diff --git a/index.html b/index.html index 92a3aee..0412287 100644 --- a/index.html +++ b/index.html @@ -1,74 +1,149 @@ - + - - - - ⚡️ Core Game Visualizer - - - - - + + + + ⚡️ Core Game Visualizer + + + + + -
-
- -
-
- -
- - -
- - -
-
- - - -
-
- -
- - -
- - -
-
-
+
+
+ +
+
+ +
+ + +
+ + +
+
+ + + +
+
+ +
+ + +
+ + +
+
+
- -
-
Team One
- -
Team Two
-
-
+ +
+
Team One
+ +
Team Two
+
+
- -
-

🎖️🎉 Winner: 🎈🏁

-

-
-
-
+ +
+

🎖️🎉 Winner: 🎈🏁

+

+
+
+
- + - - - + + + - - - + + + - -
- + +
+ diff --git a/public/assets/ui-svgs/dark-mode-moon.svg b/public/assets/ui-svgs/dark-mode-moon.svg new file mode 100644 index 0000000..0fadbe0 --- /dev/null +++ b/public/assets/ui-svgs/dark-mode-moon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/assets/ui-svgs/dark-mode-sun.svg b/public/assets/ui-svgs/dark-mode-sun.svg new file mode 100644 index 0000000..e5b25b6 --- /dev/null +++ b/public/assets/ui-svgs/dark-mode-sun.svg @@ -0,0 +1 @@ + \ No newline at end of file From 3062070c83b63354f9f6b4cdee2765c0bda4a477 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 11:06:40 +0200 Subject: [PATCH 02/16] format css also --- index.html | 32 +++- src/css/styles.css | 359 ++++++++++++++++++++++++--------------------- 2 files changed, 219 insertions(+), 172 deletions(-) diff --git a/index.html b/index.html index 0412287..6dc1bc3 100644 --- a/index.html +++ b/index.html @@ -15,8 +15,23 @@
+ + + -
+
+ + +
diff --git a/src/css/styles.css b/src/css/styles.css index e612cfc..aa5beee 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -1,274 +1,291 @@ @font-face { - font-family: "JetBrains Mono"; - src: url("/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf") - format("truetype"); + font-family: "JetBrains Mono"; + src: url("/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf") + format("truetype"); } :root { - --hp-color: #c70202ff; - --balance-color: #008600ff; - --cooldown-color: #0066ffff; - --svg-canvas-scale: 100%; - --core-purple: #6a0dad; + --hp-color: #c70202ff; + --balance-color: #008600ff; + --cooldown-color: #0066ffff; + --svg-canvas-scale: 100%; + --core-purple: #6a0dad; +} +:root { + --accent: #6a0dad; + --panel-bg: #f0f0f0; + --panel-outline: #cccccc; + --panel-track: #a4a4a4; + --panel-thumb: var(--accent); + --text: #333333; + --app-bg: color-mix(in srgb, var(--accent) 20%, white); +} +body.theme-dark { + --panel-bg: #1f1f23; + --panel-outline: #3a3a3f; + --panel-track: #4a4a50; + --panel-thumb: var(--accent); + --text: #e8e8ea; + --app-bg: #0f0f12; } html, body { - margin: 0; - padding: 0; - height: 100%; - overflow: hidden; - overscroll-behavior: none; - font-family: "JetBrains Mono", monospace; - background-color: color-mix(in srgb, var(--core-purple) 20%, white); + margin: 0; + padding: 0; + height: 100%; + overflow: hidden; + overscroll-behavior: none; + font-family: "JetBrains Mono", monospace; + background-color: color-mix(in srgb, var(--core-purple) 20%, white); } /* SVG Output Canvas */ #tooltip { - position: fixed; - display: none; - padding: 10px; - background: white; - border: 1px solid #333; - border-radius: 0 10px 10px 10px; - box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3); - pointer-events: none; + position: fixed; + display: none; + padding: 10px; + background: white; + border: 1px solid #333; + border-radius: 0 10px 10px 10px; + box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3); + pointer-events: none; } /* Structure */ .container { - display: grid; - grid-template-rows: auto 1fr auto; - height: 100vh; + display: grid; + grid-template-rows: auto 1fr auto; + height: 100vh; } .game-area { - display: grid; - grid-template-columns: 1fr max-content 1fr; - grid-template-rows: 1fr max-content 1fr; - place-items: center; + display: grid; + grid-template-columns: 1fr max-content 1fr; + grid-template-rows: 1fr max-content 1fr; + place-items: center; } #team-one-name { - place-self: start end; + place-self: start end; } #team-two-name { - place-self: end start; + place-self: end start; } .teamName { - font-size: 1.5rem; - font-weight: bold; - color: #333; - text-align: center; - background-color: #f0f0f0; - padding: 0.5rem 1rem; - margin: 10px; - border-radius: 10px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - outline: 2px solid #ccc; + font-size: 1.5rem; + font-weight: bold; + color: #333; + text-align: center; + background-color: #f0f0f0; + padding: 0.5rem 1rem; + margin: 10px; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + outline: 2px solid #ccc; } #svg-canvas { - width: var(--svg-canvas-scale); - height: var(--svg-canvas-scale); - aspect-ratio: 1 / 1; - outline: 2px solid #ccc; - background-color: #f9f9f9; - border-radius: 10px; - margin: 10px 0 10px 0; + width: var(--svg-canvas-scale); + height: var(--svg-canvas-scale); + aspect-ratio: 1 / 1; + outline: 2px solid #ccc; + background-color: #f9f9f9; + border-radius: 10px; + margin: 10px 0 10px 0; } /* Time Controls */ #time-controls { - display: flex; - align-items: center; - justify-content: space-between; - gap: 1rem; - padding: 0.5rem 1rem; - background-color: #f0f0f0; - border-radius: 0 0 20px 20px; - z-index: 5000; - width: max-content; - margin: 0 auto; - position: relative; - outline: #ccc solid 2px; + display: flex; + align-items: center; + justify-content: space-between; + gap: 1rem; + padding: 0.5rem 1rem; + background-color: #f0f0f0; + border-radius: 0 0 20px 20px; + z-index: 5000; + width: max-content; + margin: 0 auto; + position: relative; + outline: #ccc solid 2px; } .controls-bar, .main-buttons { - display: flex; - align-items: center; - gap: 0.5rem; - margin: 0 20px 0 20px; + display: flex; + align-items: center; + gap: 0.5rem; + margin: 0 20px 0 20px; } .main-buttons button { - padding: 0.75rem; - background-color: #555; + padding: 0.75rem; + background-color: #555; } .slider-group { - display: flex; - flex-direction: column; - align-items: center; - gap: 2px; - width: 6rem; - box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + gap: 2px; + width: 6rem; + box-sizing: border-box; } .slider-group label { - width: 100%; - font-size: 0.9rem; - font-weight: 600; - text-align: center; - line-height: 1.1; - margin: 0; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + width: 100%; + font-size: 0.9rem; + font-weight: 600; + text-align: center; + line-height: 1.1; + margin: 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } #time-controls button { - background: none; - border: none; - cursor: pointer; - padding: 0.5rem; - border-radius: 4px; + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + border-radius: 4px; } #time-controls button:active, #time-controls button.active { - background-color: color-mix(in srgb, var(--core-purple) 40%, white); + background-color: color-mix(in srgb, var(--core-purple) 40%, white); } #time-controls button img { - width: 1.5rem; - height: auto; + width: 1.5rem; + height: auto; } #time-controls input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 6rem; - height: 0.5rem; - background: #a4a4a4; - border-radius: 0.25rem; + -webkit-appearance: none; + appearance: none; + width: 6rem; + height: 0.5rem; + background: #a4a4a4; + border-radius: 0.25rem; } #time-controls input[type="range"]::-webkit-slider-runnable-track { - height: 100%; - background: #a4a4a4; - border-radius: 0.25rem; + height: 100%; + background: #a4a4a4; + border-radius: 0.25rem; } #time-controls input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - width: 1rem; - height: 1rem; - margin-top: -0.25rem; - background: var(--core-purple); - border-radius: 50%; - cursor: pointer; + -webkit-appearance: none; + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background: var(--core-purple); + border-radius: 50%; + cursor: pointer; } #time-controls input[type="range"] { - -moz-appearance: none; - appearance: none; + -moz-appearance: none; + appearance: none; } #time-controls input[type="range"]::-moz-range-track { - height: 0.5rem; - background: #ddd; - border-radius: 0.25rem; + height: 0.5rem; + background: #ddd; + border-radius: 0.25rem; } #time-controls input[type="range"]::-moz-range-progress { - background: var(--core-purple); - height: 0.5rem; - border-radius: 0.25rem; + background: var(--core-purple); + height: 0.5rem; + border-radius: 0.25rem; } #time-controls input[type="range"]::-moz-range-thumb { - width: 1rem; - height: 1rem; - background: var(--core-purple); - border: none; - border-radius: 50%; - cursor: pointer; + width: 1rem; + height: 1rem; + background: var(--core-purple); + border: none; + border-radius: 50%; + cursor: pointer; } #time-controls input[type="number"] { - width: 3rem; + width: 3rem; } /* corner buttons */ .corner-button { - position: absolute; - width: 7rem; - height: 7rem; - background-color: var(--core-purple); - background-size: 40%; - background-repeat: no-repeat; - transition: transform 0.1s ease-in-out; - z-index: 750; + position: absolute; + width: 7rem; + height: 7rem; + background-color: var(--core-purple); + background-size: 40%; + background-repeat: no-repeat; + transition: transform 0.1s ease-in-out; + z-index: 750; } .corner-button:hover { - transform: scale(1.1); + transform: scale(1.1); } #corner-bottom-left { - bottom: 0; - left: 0; - background-image: url("/assets/ui-svgs/github-logo.svg"); - clip-path: polygon(0 100%, 0 0, 100% 100%); - background-position: 17% 83%; - transform-origin: bottom left; + bottom: 0; + left: 0; + background-image: url("/assets/ui-svgs/github-logo.svg"); + clip-path: polygon(0 100%, 0 0, 100% 100%); + background-position: 17% 83%; + transform-origin: bottom left; } #corner-top-right { - top: 0; - right: 0; - background-image: url("/assets/ui-svgs/core-logo.svg"); - clip-path: polygon(0 0, 100% 0, 100% 100%); - background-position: 83% 17%; - transform-origin: top right; + top: 0; + right: 0; + background-image: url("/assets/ui-svgs/core-logo.svg"); + clip-path: polygon(0 0, 100% 0, 100% 100%); + background-position: 83% 17%; + transform-origin: top right; } /* Winner Display */ #win-display-box { - display: none; - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - backdrop-filter: blur(5px); - /* background-color: color-mix(in srgb, var(--core-purple) 20%, white); */ - color: white; - padding: 20px; - border-radius: 10px; - /* box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); */ - outline: 5px solid color-mix(in srgb, var(--core-purple) 20%, white); - text-align: center; - z-index: 1000; - pointer-events: none; + display: none; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + backdrop-filter: blur(5px); + /* background-color: color-mix(in srgb, var(--core-purple) 20%, white); */ + color: white; + padding: 20px; + border-radius: 10px; + /* box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); */ + outline: 5px solid color-mix(in srgb, var(--core-purple) 20%, white); + text-align: center; + z-index: 1000; + pointer-events: none; } #background-darkener { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background-color: rgba(0, 0, 0, 0.75); - z-index: 500; - pointer-events: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.75); + z-index: 500; + pointer-events: none; } .fireworks { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - z-index: 600; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + z-index: 600; } From 785993a599c14154410c091555d2f81584ed7ea9 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 11:28:49 +0200 Subject: [PATCH 03/16] improved dark mode & fullscreen button positioning --- index.html | 26 +++------- src/css/styles.css | 120 +++++++++++++++++++++++++++------------------ 2 files changed, 79 insertions(+), 67 deletions(-) diff --git a/index.html b/index.html index 6dc1bc3..56670bf 100644 --- a/index.html +++ b/index.html @@ -31,8 +31,8 @@ -
-
+
+
-
+ +
-
+ +
@@ -160,20 +162,6 @@

- -
diff --git a/src/css/styles.css b/src/css/styles.css index aa5beee..27d0a7f 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -37,7 +37,8 @@ body { overflow: hidden; overscroll-behavior: none; font-family: "JetBrains Mono", monospace; - background-color: color-mix(in srgb, var(--core-purple) 20%, white); + color: var(--text); + background-color: var(--app-bg); } /* SVG Output Canvas */ @@ -75,7 +76,7 @@ body { .teamName { font-size: 1.5rem; font-weight: bold; - color: #333; + color: var(--text); text-align: center; background-color: #f0f0f0; padding: 0.5rem 1rem; @@ -96,42 +97,59 @@ body { } /* Time Controls */ -#time-controls { +.control-panel { display: flex; align-items: center; - justify-content: space-between; + justify-content: center; gap: 1rem; padding: 0.5rem 1rem; - background-color: #f0f0f0; + background-color: var(--panel-bg); border-radius: 0 0 20px 20px; - z-index: 5000; + outline: 2px solid var(--panel-outline); width: max-content; margin: 0 auto; - position: relative; - outline: #ccc solid 2px; + z-index: 5000; } -.controls-bar, -.main-buttons { +.control-row { display: flex; align-items: center; gap: 0.5rem; - margin: 0 20px 0 20px; + margin: 0 20px; + flex-wrap: nowrap; } -.main-buttons button { - padding: 0.75rem; +.control-row.primary button { background-color: #555; } +.control-panel button { + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + border-radius: 4px; +} + +.control-panel button:active, +.control-panel button.active { + background-color: color-mix(in srgb, var(--accent) 40%, white); +} + +.control-panel button img { + width: 1.5rem; + height: auto; +} + .slider-group { display: flex; flex-direction: column; align-items: center; gap: 2px; - width: 6rem; + width: 7rem; box-sizing: border-box; } + .slider-group label { width: 100%; font-size: 0.9rem; @@ -144,76 +162,82 @@ body { text-overflow: ellipsis; } -#time-controls button { - background: none; - border: none; - cursor: pointer; - padding: 0.5rem; +.control-panel input[type="number"] { + width: 3.25rem; + color: var(--text); + background: var(--panel-bg); + border: 1px solid var(--panel-outline); border-radius: 4px; -} -#time-controls button:active, -#time-controls button.active { - background-color: color-mix(in srgb, var(--core-purple) 40%, white); -} - -#time-controls button img { - width: 1.5rem; - height: auto; + padding: 0.25rem 0.35rem; } -#time-controls input[type="range"] { +.control-panel input[type="range"] { -webkit-appearance: none; appearance: none; - width: 6rem; + width: 7rem; height: 0.5rem; - background: #a4a4a4; + background: var(--panel-track); border-radius: 0.25rem; } -#time-controls input[type="range"]::-webkit-slider-runnable-track { +.control-panel input[type="range"]::-webkit-slider-runnable-track { height: 100%; - background: #a4a4a4; + background: var(--panel-track); border-radius: 0.25rem; } -#time-controls input[type="range"]::-webkit-slider-thumb { +.control-panel input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; width: 1rem; height: 1rem; margin-top: -0.25rem; - background: var(--core-purple); + background: var(--panel-thumb); border-radius: 50%; cursor: pointer; } -#time-controls input[type="range"] { - -moz-appearance: none; - appearance: none; -} - -#time-controls input[type="range"]::-moz-range-track { +.control-panel input[type="range"]::-moz-range-track { height: 0.5rem; - background: #ddd; + background: var(--panel-track); border-radius: 0.25rem; } -#time-controls input[type="range"]::-moz-range-progress { - background: var(--core-purple); +.control-panel input[type="range"]::-moz-range-progress { + background: var(--panel-thumb); height: 0.5rem; border-radius: 0.25rem; } -#time-controls input[type="range"]::-moz-range-thumb { +.control-panel input[type="range"]::-moz-range-thumb { width: 1rem; height: 1rem; - background: var(--core-purple); + background: var(--panel-thumb); border: none; border-radius: 50%; cursor: pointer; } -#time-controls input[type="number"] { - width: 3rem; +.top-bar { + display: grid; + grid-template-columns: auto max-content auto; + align-items: start; + justify-content: center; + gap: 0.5rem; + padding: 0; +} + +.icon-button { + padding: 0.5rem 0.6rem; + background-color: var(--panel-bg); + outline: 2px solid var(--panel-outline); + border: none; + border-radius: 0 0 12px 12px; + cursor: pointer; +} +.icon-button > img { + width: 1.5rem; + height: 1.5rem; + display: block; } /* corner buttons */ From 171dc46793c8457c5e8b714192f29b9b1d12e0b1 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 11:37:40 +0200 Subject: [PATCH 04/16] clarify which coordinate is x and y in tooltip positions display --- src/css/styles.css | 404 ++++++++++++++++----------------- src/ts/renderer/renderer.ts | 2 +- src/ts/replay_loader/object.ts | 2 +- 3 files changed, 204 insertions(+), 204 deletions(-) diff --git a/src/css/styles.css b/src/css/styles.css index 27d0a7f..3c771f4 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -1,315 +1,315 @@ @font-face { - font-family: "JetBrains Mono"; - src: url("/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf") - format("truetype"); + font-family: "JetBrains Mono"; + src: url("/assets/fonts/JetBrainsMonoNerdFontMono-Regular.ttf") + format("truetype"); } :root { - --hp-color: #c70202ff; - --balance-color: #008600ff; - --cooldown-color: #0066ffff; - --svg-canvas-scale: 100%; - --core-purple: #6a0dad; + --hp-color: #c70202ff; + --balance-color: #008600ff; + --cooldown-color: #0066ffff; + --svg-canvas-scale: 100%; + --core-purple: #6a0dad; } :root { - --accent: #6a0dad; - --panel-bg: #f0f0f0; - --panel-outline: #cccccc; - --panel-track: #a4a4a4; - --panel-thumb: var(--accent); - --text: #333333; - --app-bg: color-mix(in srgb, var(--accent) 20%, white); + --accent: #6a0dad; + --panel-bg: #f0f0f0; + --panel-outline: #cccccc; + --panel-track: #a4a4a4; + --panel-thumb: var(--accent); + --text: #333333; + --app-bg: color-mix(in srgb, var(--accent) 20%, white); } body.theme-dark { - --panel-bg: #1f1f23; - --panel-outline: #3a3a3f; - --panel-track: #4a4a50; - --panel-thumb: var(--accent); - --text: #e8e8ea; - --app-bg: #0f0f12; + --panel-bg: #1f1f23; + --panel-outline: #3a3a3f; + --panel-track: #4a4a50; + --panel-thumb: var(--accent); + --text: #e8e8ea; + --app-bg: #0f0f12; } html, body { - margin: 0; - padding: 0; - height: 100%; - overflow: hidden; - overscroll-behavior: none; - font-family: "JetBrains Mono", monospace; - color: var(--text); - background-color: var(--app-bg); + margin: 0; + padding: 0; + height: 100%; + overflow: hidden; + overscroll-behavior: none; + font-family: "JetBrains Mono", monospace; + color: var(--text); + background-color: var(--app-bg); } /* SVG Output Canvas */ #tooltip { - position: fixed; - display: none; - padding: 10px; - background: white; - border: 1px solid #333; - border-radius: 0 10px 10px 10px; - box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3); - pointer-events: none; + position: fixed; + display: none; + padding: 10px; + background: white; + border: 1px solid #333; + border-radius: 0 10px 10px 10px; + box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3); + pointer-events: none; } /* Structure */ .container { - display: grid; - grid-template-rows: auto 1fr auto; - height: 100vh; + display: grid; + grid-template-rows: auto 1fr auto; + height: 100vh; } .game-area { - display: grid; - grid-template-columns: 1fr max-content 1fr; - grid-template-rows: 1fr max-content 1fr; - place-items: center; + display: grid; + grid-template-columns: 1fr max-content 1fr; + grid-template-rows: 1fr max-content 1fr; + place-items: center; } #team-one-name { - place-self: start end; + place-self: start end; } #team-two-name { - place-self: end start; + place-self: end start; } .teamName { - font-size: 1.5rem; - font-weight: bold; - color: var(--text); - text-align: center; - background-color: #f0f0f0; - padding: 0.5rem 1rem; - margin: 10px; - border-radius: 10px; - box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - outline: 2px solid #ccc; + font-size: 1.5rem; + font-weight: bold; + color: var(--text); + text-align: center; + background-color: #f0f0f0; + padding: 0.5rem 1rem; + margin: 10px; + border-radius: 10px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + outline: 2px solid #ccc; } #svg-canvas { - width: var(--svg-canvas-scale); - height: var(--svg-canvas-scale); - aspect-ratio: 1 / 1; - outline: 2px solid #ccc; - background-color: #f9f9f9; - border-radius: 10px; - margin: 10px 0 10px 0; + width: var(--svg-canvas-scale); + height: var(--svg-canvas-scale); + aspect-ratio: 1 / 1; + outline: 2px solid #ccc; + background-color: #f9f9f9; + border-radius: 10px; + margin: 10px 0 10px 0; } /* Time Controls */ .control-panel { - display: flex; - align-items: center; - justify-content: center; - gap: 1rem; - padding: 0.5rem 1rem; - background-color: var(--panel-bg); - border-radius: 0 0 20px 20px; - outline: 2px solid var(--panel-outline); - width: max-content; - margin: 0 auto; - z-index: 5000; + display: flex; + align-items: center; + justify-content: center; + gap: 1rem; + padding: 0.5rem 1rem; + background-color: var(--panel-bg); + border-radius: 0 0 20px 20px; + outline: 2px solid var(--panel-outline); + width: max-content; + margin: 0 auto; + z-index: 5000; } .control-row { - display: flex; - align-items: center; - gap: 0.5rem; - margin: 0 20px; - flex-wrap: nowrap; + display: flex; + align-items: center; + gap: 0.5rem; + margin: 0 20px; + flex-wrap: nowrap; } .control-row.primary button { - background-color: #555; + background-color: #555; } .control-panel button { - background: none; - border: none; - cursor: pointer; - padding: 0.5rem; - border-radius: 4px; + background: none; + border: none; + cursor: pointer; + padding: 0.5rem; + border-radius: 4px; } .control-panel button:active, .control-panel button.active { - background-color: color-mix(in srgb, var(--accent) 40%, white); + background-color: color-mix(in srgb, var(--accent) 40%, white); } .control-panel button img { - width: 1.5rem; - height: auto; + width: 1.5rem; + height: auto; } .slider-group { - display: flex; - flex-direction: column; - align-items: center; - gap: 2px; - width: 7rem; - box-sizing: border-box; + display: flex; + flex-direction: column; + align-items: center; + gap: 2px; + width: 7rem; + box-sizing: border-box; } .slider-group label { - width: 100%; - font-size: 0.9rem; - font-weight: 600; - text-align: center; - line-height: 1.1; - margin: 0; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; + width: 100%; + font-size: 0.9rem; + font-weight: 600; + text-align: center; + line-height: 1.1; + margin: 0; + overflow: hidden; + white-space: nowrap; + text-overflow: ellipsis; } .control-panel input[type="number"] { - width: 3.25rem; - color: var(--text); - background: var(--panel-bg); - border: 1px solid var(--panel-outline); - border-radius: 4px; - padding: 0.25rem 0.35rem; + width: 3.25rem; + color: var(--text); + background: var(--panel-bg); + border: 1px solid var(--panel-outline); + border-radius: 4px; + padding: 0.25rem 0.35rem; } .control-panel input[type="range"] { - -webkit-appearance: none; - appearance: none; - width: 7rem; - height: 0.5rem; - background: var(--panel-track); - border-radius: 0.25rem; + -webkit-appearance: none; + appearance: none; + width: 7rem; + height: 0.5rem; + background: var(--panel-track); + border-radius: 0.25rem; } .control-panel input[type="range"]::-webkit-slider-runnable-track { - height: 100%; - background: var(--panel-track); - border-radius: 0.25rem; + height: 100%; + background: var(--panel-track); + border-radius: 0.25rem; } .control-panel input[type="range"]::-webkit-slider-thumb { - -webkit-appearance: none; - width: 1rem; - height: 1rem; - margin-top: -0.25rem; - background: var(--panel-thumb); - border-radius: 50%; - cursor: pointer; + -webkit-appearance: none; + width: 1rem; + height: 1rem; + margin-top: -0.25rem; + background: var(--panel-thumb); + border-radius: 50%; + cursor: pointer; } .control-panel input[type="range"]::-moz-range-track { - height: 0.5rem; - background: var(--panel-track); - border-radius: 0.25rem; + height: 0.5rem; + background: var(--panel-track); + border-radius: 0.25rem; } .control-panel input[type="range"]::-moz-range-progress { - background: var(--panel-thumb); - height: 0.5rem; - border-radius: 0.25rem; + background: var(--panel-thumb); + height: 0.5rem; + border-radius: 0.25rem; } .control-panel input[type="range"]::-moz-range-thumb { - width: 1rem; - height: 1rem; - background: var(--panel-thumb); - border: none; - border-radius: 50%; - cursor: pointer; + width: 1rem; + height: 1rem; + background: var(--panel-thumb); + border: none; + border-radius: 50%; + cursor: pointer; } .top-bar { - display: grid; - grid-template-columns: auto max-content auto; - align-items: start; - justify-content: center; - gap: 0.5rem; - padding: 0; + display: grid; + grid-template-columns: auto max-content auto; + align-items: start; + justify-content: center; + gap: 0.5rem; + padding: 0; } .icon-button { - padding: 0.5rem 0.6rem; - background-color: var(--panel-bg); - outline: 2px solid var(--panel-outline); - border: none; - border-radius: 0 0 12px 12px; - cursor: pointer; + padding: 0.5rem 0.6rem; + background-color: var(--panel-bg); + outline: 2px solid var(--panel-outline); + border: none; + border-radius: 0 0 12px 12px; + cursor: pointer; } .icon-button > img { - width: 1.5rem; - height: 1.5rem; - display: block; + width: 1.5rem; + height: 1.5rem; + display: block; } /* corner buttons */ .corner-button { - position: absolute; - width: 7rem; - height: 7rem; - background-color: var(--core-purple); - background-size: 40%; - background-repeat: no-repeat; - transition: transform 0.1s ease-in-out; - z-index: 750; + position: absolute; + width: 7rem; + height: 7rem; + background-color: var(--core-purple); + background-size: 40%; + background-repeat: no-repeat; + transition: transform 0.1s ease-in-out; + z-index: 750; } .corner-button:hover { - transform: scale(1.1); + transform: scale(1.1); } #corner-bottom-left { - bottom: 0; - left: 0; - background-image: url("/assets/ui-svgs/github-logo.svg"); - clip-path: polygon(0 100%, 0 0, 100% 100%); - background-position: 17% 83%; - transform-origin: bottom left; + bottom: 0; + left: 0; + background-image: url("/assets/ui-svgs/github-logo.svg"); + clip-path: polygon(0 100%, 0 0, 100% 100%); + background-position: 17% 83%; + transform-origin: bottom left; } #corner-top-right { - top: 0; - right: 0; - background-image: url("/assets/ui-svgs/core-logo.svg"); - clip-path: polygon(0 0, 100% 0, 100% 100%); - background-position: 83% 17%; - transform-origin: top right; + top: 0; + right: 0; + background-image: url("/assets/ui-svgs/core-logo.svg"); + clip-path: polygon(0 0, 100% 0, 100% 100%); + background-position: 83% 17%; + transform-origin: top right; } /* Winner Display */ #win-display-box { - display: none; - position: fixed; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - backdrop-filter: blur(5px); - /* background-color: color-mix(in srgb, var(--core-purple) 20%, white); */ - color: white; - padding: 20px; - border-radius: 10px; - /* box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); */ - outline: 5px solid color-mix(in srgb, var(--core-purple) 20%, white); - text-align: center; - z-index: 1000; - pointer-events: none; + display: none; + position: fixed; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + backdrop-filter: blur(5px); + /* background-color: color-mix(in srgb, var(--core-purple) 20%, white); */ + color: white; + padding: 20px; + border-radius: 10px; + /* box-shadow: 0 0 10px rgba(255, 255, 255, 0.3); */ + outline: 5px solid color-mix(in srgb, var(--core-purple) 20%, white); + text-align: center; + z-index: 1000; + pointer-events: none; } #background-darkener { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - background-color: rgba(0, 0, 0, 0.75); - z-index: 500; - pointer-events: none; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + background-color: rgba(0, 0, 0, 0.75); + z-index: 500; + pointer-events: none; } .fireworks { - position: fixed; - top: 0; - left: 0; - width: 100vw; - height: 100vh; - z-index: 600; + position: fixed; + top: 0; + left: 0; + width: 100vw; + height: 100vh; + z-index: 600; } diff --git a/src/ts/renderer/renderer.ts b/src/ts/renderer/renderer.ts index 1a3ad00..44e265b 100644 --- a/src/ts/renderer/renderer.ts +++ b/src/ts/renderer/renderer.ts @@ -104,7 +104,7 @@ function refreshTooltipFromSVGPoint( if (obj) { tooltipElement.innerHTML = formatObjectData(obj); } else { - tooltipElement.innerHTML = `📍 Position: [${tx}, ${ty}]`; + tooltipElement.innerHTML = `📍 Position: [x: ${tx}, y: ${ty}]`; } } export async function setupRenderer(): Promise { diff --git a/src/ts/replay_loader/object.ts b/src/ts/replay_loader/object.ts index 1897f9d..afcbc4a 100644 --- a/src/ts/replay_loader/object.ts +++ b/src/ts/replay_loader/object.ts @@ -67,7 +67,7 @@ export function formatObjectData(obj: TickObject): string { }); lines.push({ line: `#️⃣ ID: ${obj.id}`, priority: 5, color: "black" }); lines.push({ - line: `📍 Position: [${obj.x}, ${obj.y}]`, + line: `📍 Position: [x: ${obj.x}, y: ${obj.y}]`, priority: 6, color: "black", }); From b89d18c13ada882f7db22b725db6873e4113948f Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 17:48:22 +0200 Subject: [PATCH 05/16] update all the svgs for ui and gameplay to not manually specify a fill, will set dynamically via theme later --- public/assets/object-svgs/bomb.svg | 2 +- public/assets/object-svgs/cores/1.svg | 2 +- public/assets/object-svgs/cores/2.svg | 2 +- public/assets/object-svgs/resource.svg | 3 --- public/assets/object-svgs/units/bomberman/1.svg | 3 --- public/assets/object-svgs/units/bomberman/2.svg | 3 --- public/assets/object-svgs/units/builder/1.svg | 2 +- public/assets/object-svgs/units/builder/2.svg | 2 +- public/assets/object-svgs/units/carrier/1.svg | 2 +- public/assets/object-svgs/units/carrier/2.svg | 2 +- public/assets/object-svgs/units/miner/1.svg | 2 +- public/assets/object-svgs/units/miner/2.svg | 2 +- public/assets/object-svgs/units/tank/1.svg | 2 +- public/assets/object-svgs/units/tank/2.svg | 2 +- public/assets/object-svgs/units/warrior/1.svg | 2 +- public/assets/object-svgs/units/warrior/2.svg | 2 +- public/assets/object-svgs/wall.svg | 4 ---- public/assets/ui-svgs/core-logo.svg | 4 ---- public/assets/ui-svgs/github-logo.svg | 2 +- public/assets/ui-svgs/pause.svg | 2 +- public/assets/ui-svgs/play.svg | 2 +- public/assets/ui-svgs/skip_end.svg | 2 +- public/assets/ui-svgs/skip_start.svg | 2 +- public/assets/ui-svgs/speed_down.svg | 2 +- public/assets/ui-svgs/speed_up.svg | 2 +- public/assets/ui-svgs/tick_next.svg | 2 +- public/assets/ui-svgs/tick_previous.svg | 2 +- 27 files changed, 22 insertions(+), 39 deletions(-) diff --git a/public/assets/object-svgs/bomb.svg b/public/assets/object-svgs/bomb.svg index 6d59085..4dfb5ea 100644 --- a/public/assets/object-svgs/bomb.svg +++ b/public/assets/object-svgs/bomb.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/cores/1.svg b/public/assets/object-svgs/cores/1.svg index 19dd949..7262d2e 100644 --- a/public/assets/object-svgs/cores/1.svg +++ b/public/assets/object-svgs/cores/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/cores/2.svg b/public/assets/object-svgs/cores/2.svg index 43750f3..d82c064 100644 --- a/public/assets/object-svgs/cores/2.svg +++ b/public/assets/object-svgs/cores/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/resource.svg b/public/assets/object-svgs/resource.svg index 15d212a..60e3b0a 100644 --- a/public/assets/object-svgs/resource.svg +++ b/public/assets/object-svgs/resource.svg @@ -14,9 +14,6 @@ id="defs2" /> diff --git a/public/assets/object-svgs/units/builder/1.svg b/public/assets/object-svgs/units/builder/1.svg index 910d4c4..9c4824a 100644 --- a/public/assets/object-svgs/units/builder/1.svg +++ b/public/assets/object-svgs/units/builder/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/builder/2.svg b/public/assets/object-svgs/units/builder/2.svg index 5a35057..6152bf5 100644 --- a/public/assets/object-svgs/units/builder/2.svg +++ b/public/assets/object-svgs/units/builder/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/carrier/1.svg b/public/assets/object-svgs/units/carrier/1.svg index 5fccfb3..cee179d 100644 --- a/public/assets/object-svgs/units/carrier/1.svg +++ b/public/assets/object-svgs/units/carrier/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/carrier/2.svg b/public/assets/object-svgs/units/carrier/2.svg index ff87f4b..a953ee5 100644 --- a/public/assets/object-svgs/units/carrier/2.svg +++ b/public/assets/object-svgs/units/carrier/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/miner/1.svg b/public/assets/object-svgs/units/miner/1.svg index f2ad10c..19c0edb 100644 --- a/public/assets/object-svgs/units/miner/1.svg +++ b/public/assets/object-svgs/units/miner/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/miner/2.svg b/public/assets/object-svgs/units/miner/2.svg index ac26189..74af943 100644 --- a/public/assets/object-svgs/units/miner/2.svg +++ b/public/assets/object-svgs/units/miner/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/tank/1.svg b/public/assets/object-svgs/units/tank/1.svg index 871a0c5..f9a33a1 100644 --- a/public/assets/object-svgs/units/tank/1.svg +++ b/public/assets/object-svgs/units/tank/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/tank/2.svg b/public/assets/object-svgs/units/tank/2.svg index fffaab5..e55c37a 100644 --- a/public/assets/object-svgs/units/tank/2.svg +++ b/public/assets/object-svgs/units/tank/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/warrior/1.svg b/public/assets/object-svgs/units/warrior/1.svg index 45ad532..5dee38d 100644 --- a/public/assets/object-svgs/units/warrior/1.svg +++ b/public/assets/object-svgs/units/warrior/1.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/units/warrior/2.svg b/public/assets/object-svgs/units/warrior/2.svg index 52cd1cc..aacbd38 100644 --- a/public/assets/object-svgs/units/warrior/2.svg +++ b/public/assets/object-svgs/units/warrior/2.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/object-svgs/wall.svg b/public/assets/object-svgs/wall.svg index ec1f5ac..3796566 100644 --- a/public/assets/object-svgs/wall.svg +++ b/public/assets/object-svgs/wall.svg @@ -15,9 +15,6 @@ id="defs1" /> diff --git a/public/assets/ui-svgs/core-logo.svg b/public/assets/ui-svgs/core-logo.svg index ab8d69a..1820a7b 100644 --- a/public/assets/ui-svgs/core-logo.svg +++ b/public/assets/ui-svgs/core-logo.svg @@ -18,9 +18,6 @@ id="defs1" /> diff --git a/public/assets/ui-svgs/github-logo.svg b/public/assets/ui-svgs/github-logo.svg index d5e6491..4df6bde 100644 --- a/public/assets/ui-svgs/github-logo.svg +++ b/public/assets/ui-svgs/github-logo.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/public/assets/ui-svgs/pause.svg b/public/assets/ui-svgs/pause.svg index f78e5c1..bafcfde 100644 --- a/public/assets/ui-svgs/pause.svg +++ b/public/assets/ui-svgs/pause.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/play.svg b/public/assets/ui-svgs/play.svg index 566dacb..915c223 100644 --- a/public/assets/ui-svgs/play.svg +++ b/public/assets/ui-svgs/play.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/skip_end.svg b/public/assets/ui-svgs/skip_end.svg index ea4913f..33a23a8 100644 --- a/public/assets/ui-svgs/skip_end.svg +++ b/public/assets/ui-svgs/skip_end.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/skip_start.svg b/public/assets/ui-svgs/skip_start.svg index 0b1c2a6..a7ac94e 100644 --- a/public/assets/ui-svgs/skip_start.svg +++ b/public/assets/ui-svgs/skip_start.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/speed_down.svg b/public/assets/ui-svgs/speed_down.svg index 0dcd517..201518e 100644 --- a/public/assets/ui-svgs/speed_down.svg +++ b/public/assets/ui-svgs/speed_down.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/speed_up.svg b/public/assets/ui-svgs/speed_up.svg index 3f6d0ff..8993c19 100644 --- a/public/assets/ui-svgs/speed_up.svg +++ b/public/assets/ui-svgs/speed_up.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/tick_next.svg b/public/assets/ui-svgs/tick_next.svg index 3b486d0..cc2ab6d 100644 --- a/public/assets/ui-svgs/tick_next.svg +++ b/public/assets/ui-svgs/tick_next.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file diff --git a/public/assets/ui-svgs/tick_previous.svg b/public/assets/ui-svgs/tick_previous.svg index bb25fb1..6240e7b 100644 --- a/public/assets/ui-svgs/tick_previous.svg +++ b/public/assets/ui-svgs/tick_previous.svg @@ -1,3 +1,3 @@ - + \ No newline at end of file From b3b42ec85b6db70c39f661988495e93f64b1cb2f Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 17:52:17 +0200 Subject: [PATCH 06/16] fix not all svgs iwhtout specified fill from previous commit --- public/assets/ui-svgs/core-logo.svg | 1 - public/assets/ui-svgs/github-logo.svg | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/public/assets/ui-svgs/core-logo.svg b/public/assets/ui-svgs/core-logo.svg index 1820a7b..d4333e0 100644 --- a/public/assets/ui-svgs/core-logo.svg +++ b/public/assets/ui-svgs/core-logo.svg @@ -1,6 +1,5 @@ \ No newline at end of file + \ No newline at end of file From 28cfb4e4d12e29e40b1a81cc59f11639b73966fe Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 21:18:06 +0200 Subject: [PATCH 07/16] a lot of css is kinda broken but yes the basic dark mode swithc works now --- index.html | 2 +- src/css/styles.css | 26 ++++++++------- src/ts/input_manager/themeManager.ts | 33 +++++++++++++++++++ .../timeManager.ts | 3 ++ src/ts/main.ts | 2 +- src/ts/renderer/renderer.ts | 2 +- src/ts/replay_loader/replayLoader.ts | 2 +- 7 files changed, 54 insertions(+), 16 deletions(-) create mode 100644 src/ts/input_manager/themeManager.ts rename src/ts/{time_manager => input_manager}/timeManager.ts (98%) diff --git a/index.html b/index.html index 56670bf..a09c774 100644 --- a/index.html +++ b/index.html @@ -1,5 +1,5 @@ - + diff --git a/src/css/styles.css b/src/css/styles.css index 3c771f4..f728538 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -4,28 +4,30 @@ format("truetype"); } -:root { +:root[data-theme="light"] { --hp-color: #c70202ff; --balance-color: #008600ff; --cooldown-color: #0066ffff; - --svg-canvas-scale: 100%; + --core-purple: #6a0dad; -} -:root { - --accent: #6a0dad; + --panel-bg: #f0f0f0; --panel-outline: #cccccc; --panel-track: #a4a4a4; - --panel-thumb: var(--accent); + --panel-thumb: var(--core-purple); + --text: #333333; - --app-bg: color-mix(in srgb, var(--accent) 20%, white); + + --app-bg: color-mix(in srgb, var(--core-purple) 20%, white); } -body.theme-dark { +:root[data-theme="dark"] { --panel-bg: #1f1f23; --panel-outline: #3a3a3f; --panel-track: #4a4a50; - --panel-thumb: var(--accent); + --panel-thumb: var(--core-purple); + --text: #e8e8ea; + --app-bg: #0f0f12; } @@ -87,8 +89,8 @@ body { } #svg-canvas { - width: var(--svg-canvas-scale); - height: var(--svg-canvas-scale); + width: 100%; + height: 100%; aspect-ratio: 1 / 1; outline: 2px solid #ccc; background-color: #f9f9f9; @@ -133,7 +135,7 @@ body { .control-panel button:active, .control-panel button.active { - background-color: color-mix(in srgb, var(--accent) 40%, white); + background-color: color-mix(in srgb, var(--core-purple) 40%, white); } .control-panel button img { diff --git a/src/ts/input_manager/themeManager.ts b/src/ts/input_manager/themeManager.ts new file mode 100644 index 0000000..42e8fe1 --- /dev/null +++ b/src/ts/input_manager/themeManager.ts @@ -0,0 +1,33 @@ +const themeToggleButton = document.getElementById( + "theme-toggle-button", +) as HTMLButtonElement; +const themeIcon = document.getElementById("theme-icon") as HTMLImageElement; + +type ThemeMode = "light" | "dark"; + +function getSavedTheme(): ThemeMode { + const v = localStorage.getItem("ui.theme"); + return v === "dark" ? "dark" : "light"; +} +export function applyTheme(mode: ThemeMode): void { + document.documentElement.setAttribute("data-theme", mode); + localStorage.setItem("ui.theme", mode); + updateThemeUI(mode); +} +function updateThemeUI(mode: ThemeMode): void { + const isDark = mode === "dark"; + if (themeToggleButton) + themeToggleButton.setAttribute("aria-pressed", isDark ? "true" : "false"); + if (themeIcon) { + themeIcon.src = isDark + ? "/assets/ui-svgs/dark-mode-sun.svg" + : "/assets/ui-svgs/dark-mode-moon.svg"; + themeIcon.alt = isDark ? "Switch to Light Mode" : "Switch to Dark Mode"; + } +} +export function toggleTheme(): void { + const next = getSavedTheme() === "dark" ? "light" : "dark"; + applyTheme(next); +} + +themeToggleButton.addEventListener("click", toggleTheme); diff --git a/src/ts/time_manager/timeManager.ts b/src/ts/input_manager/timeManager.ts similarity index 98% rename from src/ts/time_manager/timeManager.ts rename to src/ts/input_manager/timeManager.ts index 57fe026..5aa1d49 100644 --- a/src/ts/time_manager/timeManager.ts +++ b/src/ts/input_manager/timeManager.ts @@ -1,5 +1,6 @@ import { setRenderFireworks } from "../renderer/fireworksRenderer"; import { getTotalReplayTicks } from "../replay_loader/replayLoader"; +import { applyTheme } from "./themeManager"; const playButton = document.getElementById( "play-pause-button", @@ -291,6 +292,8 @@ export async function setupTimeManager() { button: speedDownButton, }, f: { action: () => toggleFullscreen(), button: fullscreenToggleButton }, + d: { action: () => applyTheme("dark") }, + l: { action: () => applyTheme("light") }, }; window.addEventListener("keydown", (event) => { diff --git a/src/ts/main.ts b/src/ts/main.ts index 2350e55..d9036a8 100644 --- a/src/ts/main.ts +++ b/src/ts/main.ts @@ -25,7 +25,7 @@ window.addEventListener("DOMContentLoaded", async () => { const { setupReplayLoader } = await import("./replay_loader/replayLoader.js"); const { setupTimeManager, startPlayback, isAtEnd } = await import( - "./time_manager/timeManager.js" + "./input_manager/timeManager.js" ); const { setupRenderer } = await import("./renderer/renderer.js"); diff --git a/src/ts/renderer/renderer.ts b/src/ts/renderer/renderer.ts index 44e265b..2b8eaff 100644 --- a/src/ts/renderer/renderer.ts +++ b/src/ts/renderer/renderer.ts @@ -1,3 +1,4 @@ +import { getCurrentTickData, isDirty } from "../input_manager/timeManager"; import type { GameConfig } from "../replay_loader/config"; import { formatObjectData, type TickObject } from "../replay_loader/object"; import { @@ -5,7 +6,6 @@ import { getGameMisc, getStateAt, } from "../replay_loader/replayLoader"; -import { getCurrentTickData, isDirty } from "../time_manager/timeManager"; import { calcAndDrawObject, initializeTeamMapping } from "./objectRenderer"; const svgNS = "http://www.w3.org/2000/svg"; diff --git a/src/ts/replay_loader/replayLoader.ts b/src/ts/replay_loader/replayLoader.ts index 31a08da..15b34b6 100644 --- a/src/ts/replay_loader/replayLoader.ts +++ b/src/ts/replay_loader/replayLoader.ts @@ -1,5 +1,5 @@ +import { resetTimeManager } from "../input_manager/timeManager"; import { setupRenderer } from "../renderer/renderer"; -import { resetTimeManager } from "../time_manager/timeManager"; import type { TickAction } from "./action"; import type { GameConfig } from "./config"; import type { TickObject } from "./object"; From 0354fa87ce7e1d936e8789fefd45e7b971fe4243 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 21:47:56 +0200 Subject: [PATCH 08/16] fix broken svg sizing --- src/css/styles.css | 15 +++++++++++++-- src/ts/input_manager/themeManager.ts | 3 +++ src/ts/main.ts | 5 +++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/css/styles.css b/src/css/styles.css index f728538..c0e8627 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -4,6 +4,9 @@ format("truetype"); } +:root { + --svg-canvas-scale: 100%; +} :root[data-theme="light"] { --hp-color: #c70202ff; --balance-color: #008600ff; @@ -19,6 +22,8 @@ --text: #333333; --app-bg: color-mix(in srgb, var(--core-purple) 20%, white); + + --svg-icon-fill: #000000; } :root[data-theme="dark"] { --panel-bg: #1f1f23; @@ -29,6 +34,8 @@ --text: #e8e8ea; --app-bg: #0f0f12; + + --svg-icon-fill: #ffffff; } html, @@ -55,6 +62,10 @@ body { pointer-events: none; } +svg path { + fill: var(--svg-icon-fill); +} + /* Structure */ .container { display: grid; @@ -89,8 +100,8 @@ body { } #svg-canvas { - width: 100%; - height: 100%; + width: var(--svg-canvas-scale); + height: var(--svg-canvas-scale); aspect-ratio: 1 / 1; outline: 2px solid #ccc; background-color: #f9f9f9; diff --git a/src/ts/input_manager/themeManager.ts b/src/ts/input_manager/themeManager.ts index 42e8fe1..fc266ad 100644 --- a/src/ts/input_manager/themeManager.ts +++ b/src/ts/input_manager/themeManager.ts @@ -25,6 +25,9 @@ function updateThemeUI(mode: ThemeMode): void { themeIcon.alt = isDark ? "Switch to Light Mode" : "Switch to Dark Mode"; } } +export function loadSavedTheme(): void { + applyTheme(getSavedTheme()); +} export function toggleTheme(): void { const next = getSavedTheme() === "dark" ? "light" : "dark"; applyTheme(next); diff --git a/src/ts/main.ts b/src/ts/main.ts index d9036a8..14267a7 100644 --- a/src/ts/main.ts +++ b/src/ts/main.ts @@ -1,3 +1,5 @@ +import { loadSavedTheme } from "./input_manager/themeManager.js"; + const svgCanvas = document.getElementById("svg-canvas") as HTMLElement; window.addEventListener("DOMContentLoaded", async () => { @@ -73,4 +75,7 @@ window.addEventListener("DOMContentLoaded", async () => { window.addEventListener("resize", updateSvgSize); window.addEventListener("load", updateSvgSize); updateSvgSize(); + + // theme + loadSavedTheme(); }); From 42ba9b578ccf25284d7c6a2c3f6623b1cd479b7f Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 22:15:55 +0200 Subject: [PATCH 09/16] basic readability functional again, almost done with everything outside of game itself --- src/css/styles.css | 56 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/src/css/styles.css b/src/css/styles.css index c0e8627..4442b45 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -6,14 +6,14 @@ :root { --svg-canvas-scale: 100%; + + --core-purple: #6a0dad; } :root[data-theme="light"] { --hp-color: #c70202ff; --balance-color: #008600ff; --cooldown-color: #0066ffff; - --core-purple: #6a0dad; - --panel-bg: #f0f0f0; --panel-outline: #cccccc; --panel-track: #a4a4a4; @@ -23,6 +23,8 @@ --app-bg: color-mix(in srgb, var(--core-purple) 20%, white); + --corner-buttons-color: var(--core-purple); + --svg-icon-fill: #000000; } :root[data-theme="dark"] { @@ -33,7 +35,9 @@ --text: #e8e8ea; - --app-bg: #0f0f12; + --app-bg: color-mix(in srgb, var(--core-purple) 40%, black); + + --corner-buttons-color: color-mix(in srgb, var(--core-purple) 35%, white); --svg-icon-fill: #ffffff; } @@ -91,12 +95,12 @@ svg path { font-weight: bold; color: var(--text); text-align: center; - background-color: #f0f0f0; + background-color: var(--panel-bg); + outline: 2px solid var(--panel-outline); padding: 0.5rem 1rem; margin: 10px; border-radius: 10px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); - outline: 2px solid #ccc; } #svg-canvas { @@ -114,7 +118,7 @@ svg path { display: flex; align-items: center; justify-content: center; - gap: 1rem; + gap: 3.5rem; padding: 0.5rem 1rem; background-color: var(--panel-bg); border-radius: 0 0 20px 20px; @@ -128,7 +132,7 @@ svg path { display: flex; align-items: center; gap: 0.5rem; - margin: 0 20px; + margin: 0; flex-wrap: nowrap; } @@ -237,6 +241,7 @@ svg path { justify-content: center; gap: 0.5rem; padding: 0; + z-index: 5000; } .icon-button { @@ -253,13 +258,18 @@ svg path { display: block; } +:root[data-theme="dark"] .icon-button > img, +:root[data-theme="dark"] .control-panel button img { + filter: invert(1); +} + /* corner buttons */ .corner-button { position: absolute; width: 7rem; height: 7rem; - background-color: var(--core-purple); + background-color: var(--corner-buttons-color); background-size: 40%; background-repeat: no-repeat; transition: transform 0.1s ease-in-out; @@ -272,20 +282,42 @@ svg path { #corner-bottom-left { bottom: 0; left: 0; - background-image: url("/assets/ui-svgs/github-logo.svg"); clip-path: polygon(0 100%, 0 0, 100% 100%); - background-position: 17% 83%; transform-origin: bottom left; } +#corner-bottom-left::after { + content: ""; + position: absolute; + inset: 0; + background-image: url("/assets/ui-svgs/github-logo.svg"); + background-size: 40%; + background-repeat: no-repeat; + background-position: 17% 83%; + pointer-events: none; +} +:root[data-theme="light"] #corner-bottom-left::after { + filter: invert(1); +} #corner-top-right { top: 0; right: 0; - background-image: url("/assets/ui-svgs/core-logo.svg"); clip-path: polygon(0 0, 100% 0, 100% 100%); - background-position: 83% 17%; transform-origin: top right; } +#corner-top-right::after { + content: ""; + position: absolute; + inset: 0; + background-image: url("/assets/ui-svgs/core-logo.svg"); + background-size: 40%; + background-repeat: no-repeat; + background-position: 83% 17%; + pointer-events: none; +} +:root[data-theme="light"] #corner-top-right::after { + filter: invert(1); +} /* Winner Display */ From 599fb15954cc3072f41effb83d134deee1425996 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Tue, 19 Aug 2025 22:33:33 +0200 Subject: [PATCH 10/16] refactor theme colors and button styles for improved accessibility --- src/css/styles.css | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/css/styles.css b/src/css/styles.css index 4442b45..975a675 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -28,10 +28,10 @@ --svg-icon-fill: #000000; } :root[data-theme="dark"] { - --panel-bg: #1f1f23; - --panel-outline: #3a3a3f; - --panel-track: #4a4a50; - --panel-thumb: var(--core-purple); + --panel-bg: #4d4d73; + --panel-outline: #9f9fe3; + --panel-track: #6f6fd6; + --panel-thumb: color-mix(in srgb, var(--core-purple) 30%, white); --text: #e8e8ea; @@ -136,10 +136,6 @@ svg path { flex-wrap: nowrap; } -.control-row.primary button { - background-color: #555; -} - .control-panel button { background: none; border: none; @@ -148,9 +144,21 @@ svg path { border-radius: 4px; } -.control-panel button:active, -.control-panel button.active { - background-color: color-mix(in srgb, var(--core-purple) 40%, white); +:root[data-theme="light"] .control-panel button.active, +:root[data-theme="light"] .control-panel button:active { + background-color: color-mix(in srgb, var(--core-purple) 30%, white); +} +:root[data-theme="dark"] .control-panel button.active, +:root[data-theme="dark"] .control-panel button:active { + background-color: color-mix(in srgb, var(--core-purple) 80%, black); +} +:root[data-theme="light"] .icon-button.active, +:root[data-theme="light"] .icon-button:active { + background-color: color-mix(in srgb, var(--core-purple) 30%, white); +} +:root[data-theme="dark"] .icon-button.active, +:root[data-theme="dark"] .icon-button:active { + background-color: color-mix(in srgb, var(--core-purple) 80%, black); } .control-panel button img { From d6545caaffc6f8039cf35460c65ee66757d7bf10 Mon Sep 17 00:00:00 2001 From: flomero <49640251+flomero@users.noreply.github.com> Date: Wed, 20 Aug 2025 08:27:12 +0200 Subject: [PATCH 11/16] dark mode grid and objects --- package.json | 2 +- src/css/styles.css | 36 +++++++++++++++++++++---------- src/ts/renderer/objectRenderer.ts | 4 ++-- src/ts/renderer/renderer.ts | 4 +--- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index fa983b7..70890e1 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "fireworks-js": "^2.10.8" }, "lint-staged": { - "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc}": [ + "*.{js,ts,cjs,mjs,d.cts,d.mts,jsx,tsx,json,jsonc,css}": [ "biome check --write --no-errors-on-unmatched" ] } diff --git a/src/css/styles.css b/src/css/styles.css index 975a675..4335ecc 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -42,6 +42,11 @@ --svg-icon-fill: #ffffff; } +:root[data-theme="dark"] .game-object { + filter: invert(100%) sepia(96%) saturate(17%) hue-rotate(214deg) + brightness(104%) contrast(100); +} + html, body { margin: 0; @@ -111,6 +116,14 @@ svg path { background-color: #f9f9f9; border-radius: 10px; margin: 10px 0 10px 0; + color: var(--svg-icon-fill); +} + +.grid-cell { + fill: var(--panel-bg); + stroke: var(--panel-outline); + stroke-width: 0.1; + pointer-events: none; } /* Time Controls */ @@ -144,6 +157,17 @@ svg path { border-radius: 4px; } +.icon-button img { + width: 1.5rem; + height: 1.5rem; + display: block; +} + +.control-panel button img { + width: 1.5rem; + height: auto; +} + :root[data-theme="light"] .control-panel button.active, :root[data-theme="light"] .control-panel button:active { background-color: color-mix(in srgb, var(--core-purple) 30%, white); @@ -161,11 +185,6 @@ svg path { background-color: color-mix(in srgb, var(--core-purple) 80%, black); } -.control-panel button img { - width: 1.5rem; - height: auto; -} - .slider-group { display: flex; flex-direction: column; @@ -260,13 +279,8 @@ svg path { border-radius: 0 0 12px 12px; cursor: pointer; } -.icon-button > img { - width: 1.5rem; - height: 1.5rem; - display: block; -} -:root[data-theme="dark"] .icon-button > img, +:root[data-theme="dark"] .icon-button img, :root[data-theme="dark"] .control-panel button img { filter: invert(1); } diff --git a/src/ts/renderer/objectRenderer.ts b/src/ts/renderer/objectRenderer.ts index 4dbf276..e0dadea 100644 --- a/src/ts/renderer/objectRenderer.ts +++ b/src/ts/renderer/objectRenderer.ts @@ -1,10 +1,10 @@ +import type { tickData } from "../input_manager/timeManager"; import { getBarMetrics, type TickObject } from "../replay_loader/object"; import { getActionsByExecutor, getNameOfUnitType, getStateAt, } from "../replay_loader/replayLoader"; -import type { tickData } from "../time_manager/timeManager"; import { EaseInOutTimingCurve, MidTickIncreaseTimingCurve, @@ -202,7 +202,7 @@ function drawObject( img = document.createElementNS(svgNS, "image"); img.setAttribute("data-obj-id", obj.id.toString()); } - + img.classList.add("game-object"); img.classList.remove("not-touched"); img.classList.remove("team-0", "team-1"); if (obj.type === 0 || obj.type === 1) { diff --git a/src/ts/renderer/renderer.ts b/src/ts/renderer/renderer.ts index 2b8eaff..18731f7 100644 --- a/src/ts/renderer/renderer.ts +++ b/src/ts/renderer/renderer.ts @@ -151,13 +151,11 @@ export async function setupRenderer(): Promise { for (let y = 0; y < gridSize; y++) { for (let x = 0; x < gridSize; x++) { const rect = document.createElementNS(svgNS, "rect"); - rect.setAttribute("class", "persistent"); + rect.setAttribute("class", "grid-cell persistent"); rect.setAttribute("x", x.toString()); rect.setAttribute("y", y.toString()); rect.setAttribute("width", "1"); rect.setAttribute("height", "1"); - rect.setAttribute("fill", "#f7f7f7"); - rect.setAttribute("stroke", "black"); rect.setAttribute("stroke-width", "0.01"); svgCanvas.appendChild(rect); } From a66bc8d6e6c274dde33715076a9577b72915bdcd Mon Sep 17 00:00:00 2001 From: flomero <49640251+flomero@users.noreply.github.com> Date: Wed, 20 Aug 2025 08:43:31 +0200 Subject: [PATCH 12/16] status colors in dark mode --- src/css/styles.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/css/styles.css b/src/css/styles.css index 4335ecc..d585312 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -28,6 +28,9 @@ --svg-icon-fill: #000000; } :root[data-theme="dark"] { + --hp-color: #c70202ff; + --balance-color: #008600ff; + --cooldown-color: #0066ffff; --panel-bg: #4d4d73; --panel-outline: #9f9fe3; --panel-track: #6f6fd6; From 1177e12cef38fac0d6b89001f6a6930e3a3d51fc Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Wed, 20 Aug 2025 15:07:26 +0200 Subject: [PATCH 13/16] various css dark mode tweaks, no more gridlines --- src/css/styles.css | 58 +++++++++++++++++++--------------- src/ts/renderer/renderer.ts | 1 - src/ts/replay_loader/object.ts | 12 +++---- 3 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/css/styles.css b/src/css/styles.css index d585312..c3e9982 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -14,23 +14,27 @@ --balance-color: #008600ff; --cooldown-color: #0066ffff; - --panel-bg: #f0f0f0; - --panel-outline: #cccccc; + --panel-bg: color-mix(in srgb, var(--core-purple) 7%, white); + --panel-outline: color-mix(in srgb, var(--core-purple) 50%, white); --panel-track: #a4a4a4; --panel-thumb: var(--core-purple); --text: #333333; - --app-bg: color-mix(in srgb, var(--core-purple) 20%, white); + --app-bg: color-mix(in srgb, var(--core-purple) 25%, white); + --grid-bg: var(--panel-bg); --corner-buttons-color: var(--core-purple); --svg-icon-fill: #000000; + + --fireworks-darkening-layer: rgba(0, 0, 0, 0.75); } :root[data-theme="dark"] { - --hp-color: #c70202ff; - --balance-color: #008600ff; + --hp-color: rgb(242, 12, 12); + --balance-color: rgb(0, 215, 0); --cooldown-color: #0066ffff; + --panel-bg: #4d4d73; --panel-outline: #9f9fe3; --panel-track: #6f6fd6; @@ -39,10 +43,13 @@ --text: #e8e8ea; --app-bg: color-mix(in srgb, var(--core-purple) 40%, black); + --grid-bg: color-mix(in srgb, var(--panel-bg) 50%, black); --corner-buttons-color: color-mix(in srgb, var(--core-purple) 35%, white); --svg-icon-fill: #ffffff; + + --fireworks-darkening-layer: rgba(0, 0, 0, 0.5); } :root[data-theme="dark"] .game-object { @@ -63,14 +70,31 @@ body { } /* SVG Output Canvas */ +#svg-canvas { + width: var(--svg-canvas-scale); + height: var(--svg-canvas-scale); + aspect-ratio: 1 / 1; + outline: 2px solid var(--panel-outline); + background-color: var(--grid-bg); + border-radius: 10px; + margin: 10px 0 10px 0; + color: var(--svg-icon-fill); +} + +.grid-cell { + fill: var(--grid-bg); + pointer-events: none; +} + #tooltip { position: fixed; display: none; padding: 10px; - background: white; - border: 1px solid #333; + background: var(--panel-bg); + border: 1px solid var(--panel-outline); border-radius: 0 10px 10px 10px; box-shadow: 0 0 10px 2px rgba(0, 0, 0, 0.3); + color: var(--text); pointer-events: none; } @@ -111,24 +135,6 @@ svg path { box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } -#svg-canvas { - width: var(--svg-canvas-scale); - height: var(--svg-canvas-scale); - aspect-ratio: 1 / 1; - outline: 2px solid #ccc; - background-color: #f9f9f9; - border-radius: 10px; - margin: 10px 0 10px 0; - color: var(--svg-icon-fill); -} - -.grid-cell { - fill: var(--panel-bg); - stroke: var(--panel-outline); - stroke-width: 0.1; - pointer-events: none; -} - /* Time Controls */ .control-panel { display: flex; @@ -370,7 +376,7 @@ svg path { left: 0; width: 100vw; height: 100vh; - background-color: rgba(0, 0, 0, 0.75); + background-color: var(--fireworks-darkening-layer); z-index: 500; pointer-events: none; } diff --git a/src/ts/renderer/renderer.ts b/src/ts/renderer/renderer.ts index 18731f7..63dbc29 100644 --- a/src/ts/renderer/renderer.ts +++ b/src/ts/renderer/renderer.ts @@ -156,7 +156,6 @@ export async function setupRenderer(): Promise { rect.setAttribute("y", y.toString()); rect.setAttribute("width", "1"); rect.setAttribute("height", "1"); - rect.setAttribute("stroke-width", "0.01"); svgCanvas.appendChild(rect); } } diff --git a/src/ts/replay_loader/object.ts b/src/ts/replay_loader/object.ts index afcbc4a..a612266 100644 --- a/src/ts/replay_loader/object.ts +++ b/src/ts/replay_loader/object.ts @@ -63,13 +63,13 @@ export function formatObjectData(obj: TickObject): string { lines.push({ line: `❓ Object Type: ${objectTypeNames[obj.type] || "Unknown"}`, priority: 4, - color: "black", + color: "var(--text)", }); - lines.push({ line: `#️⃣ ID: ${obj.id}`, priority: 5, color: "black" }); + lines.push({ line: `#️⃣ ID: ${obj.id}`, priority: 5, color: "var(--text)" }); lines.push({ line: `📍 Position: [x: ${obj.x}, y: ${obj.y}]`, priority: 6, - color: "black", + color: "var(--text)", }); switch (obj.type) { @@ -77,7 +77,7 @@ export function formatObjectData(obj: TickObject): string { lines.push({ line: `🏁 Team ID: ${obj.teamId}`, priority: 5, - color: "black", + color: "var(--text)", }); lines.push({ line: `💰 Balance: ${obj.balance}`, @@ -89,7 +89,7 @@ export function formatObjectData(obj: TickObject): string { lines.push({ line: `🏁 Team ID: ${obj.teamId}`, priority: 5, - color: "black", + color: "var(--text)", }); lines.push({ line: `💰 Balance: ${obj.balance}`, @@ -114,7 +114,7 @@ export function formatObjectData(obj: TickObject): string { lines.push({ line: `💣 Explosion Countdown: ${obj.countdown}`, priority: -1, - color: "black", + color: "var(--text)", }); break; } From a69f79bb40a2b409f180441351cf314cf1b43390 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Wed, 20 Aug 2025 17:12:09 +0200 Subject: [PATCH 14/16] text shadow behind colored tooltip lines for improved readability --- src/css/styles.css | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/css/styles.css b/src/css/styles.css index c3e9982..29cb11b 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -20,6 +20,7 @@ --panel-thumb: var(--core-purple); --text: #333333; + --tooltip-shadow-contrast: #ffffff; --app-bg: color-mix(in srgb, var(--core-purple) 25%, white); --grid-bg: var(--panel-bg); @@ -41,6 +42,7 @@ --panel-thumb: color-mix(in srgb, var(--core-purple) 30%, white); --text: #e8e8ea; + --tooltip-shadow-contrast: #000000; --app-bg: color-mix(in srgb, var(--core-purple) 40%, black); --grid-bg: color-mix(in srgb, var(--panel-bg) 50%, black); @@ -97,6 +99,13 @@ body { color: var(--text); pointer-events: none; } +#tooltip span[style*="var(--hp-color)"], +#tooltip span[style*="var(--balance-color)"], +#tooltip span[style*="var(--cooldown-color)"] { + text-shadow: + 0 0 2px var(--tooltip-shadow-contrast), + 0 0 4px var(--tooltip-shadow-contrast); +} svg path { fill: var(--svg-icon-fill); From 8dcbbaff4e8c01140a8ea2f6848819984017eb48 Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Wed, 20 Aug 2025 17:39:16 +0200 Subject: [PATCH 15/16] lower opacity outline icon units & core for clearer visual team differentiation --- src/css/styles.css | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/css/styles.css b/src/css/styles.css index 29cb11b..0a79a48 100644 --- a/src/css/styles.css +++ b/src/css/styles.css @@ -58,6 +58,12 @@ filter: invert(100%) sepia(96%) saturate(17%) hue-rotate(214deg) brightness(104%) contrast(100); } +:root[data-theme="light"] .game-object.team-1 { + opacity: 0.5; +} +:root[data-theme="dark"] .game-object.team-1 { + opacity: 0.7; +} html, body { From 27396c774b439a728108e3245fff5994f74262ab Mon Sep 17 00:00:00 2001 From: FreddyMSchubert Date: Wed, 20 Aug 2025 18:14:13 +0200 Subject: [PATCH 16/16] automatic user device color scheme detection and loading --- index.html | 318 ++++++++++++++------------- src/ts/input_manager/themeManager.ts | 78 +++++-- 2 files changed, 220 insertions(+), 176 deletions(-) diff --git a/index.html b/index.html index a09c774..ca31536 100644 --- a/index.html +++ b/index.html @@ -1,167 +1,177 @@ - - - - ⚡️ Core Game Visualizer - - - - - + + + + ⚡️ Core Game Visualizer + + + + + + -
-
- - +
+
+ + - -
-
- -
- - -
- - -
+ +
+
+ +
+ + +
+ + +
-
- - - -
+
+ + + +
-
- -
- - -
- - -
-
+
+ +
+ + +
+ + +
+
- - -
+ + +
- -
-
Team One
- -
Team Two
-
-
+ +
+
Team One
+ +
Team Two
+
+
- -
-

🎖️🎉 Winner: 🎈🏁

-

-
-
-
+ +
+

🎖️🎉 Winner: 🎈🏁

+

+
+
+
- + - - - + + + - - - -
- + + + +
+ diff --git a/src/ts/input_manager/themeManager.ts b/src/ts/input_manager/themeManager.ts index fc266ad..ed7cc0e 100644 --- a/src/ts/input_manager/themeManager.ts +++ b/src/ts/input_manager/themeManager.ts @@ -1,36 +1,70 @@ +type ThemeMode = "light" | "dark"; + const themeToggleButton = document.getElementById( "theme-toggle-button", -) as HTMLButtonElement; -const themeIcon = document.getElementById("theme-icon") as HTMLImageElement; +) as HTMLButtonElement | null; +const themeIcon = document.getElementById( + "theme-icon", +) as HTMLImageElement | null; -type ThemeMode = "light" | "dark"; +const STORAGE_KEY = "ui.theme"; +const mql = window.matchMedia + ? window.matchMedia("(prefers-color-scheme: dark)") + : null; -function getSavedTheme(): ThemeMode { - const v = localStorage.getItem("ui.theme"); - return v === "dark" ? "dark" : "light"; +function resolveTheme(): ThemeMode { + const v = localStorage.getItem(STORAGE_KEY); + if (v === "light" || v === "dark") return v as ThemeMode; + return mql?.matches ? "dark" : "light"; } -export function applyTheme(mode: ThemeMode): void { + +function applyToDOM(mode: ThemeMode): void { document.documentElement.setAttribute("data-theme", mode); - localStorage.setItem("ui.theme", mode); - updateThemeUI(mode); -} -function updateThemeUI(mode: ThemeMode): void { - const isDark = mode === "dark"; if (themeToggleButton) - themeToggleButton.setAttribute("aria-pressed", isDark ? "true" : "false"); + themeToggleButton.setAttribute( + "aria-pressed", + mode === "dark" ? "true" : "false", + ); if (themeIcon) { - themeIcon.src = isDark - ? "/assets/ui-svgs/dark-mode-sun.svg" - : "/assets/ui-svgs/dark-mode-moon.svg"; - themeIcon.alt = isDark ? "Switch to Light Mode" : "Switch to Dark Mode"; + themeIcon.src = + mode === "dark" + ? "/assets/ui-svgs/dark-mode-sun.svg" + : "/assets/ui-svgs/dark-mode-moon.svg"; + themeIcon.alt = + mode === "dark" ? "Switch to Light Mode" : "Switch to Dark Mode"; } } + +export function applyTheme(mode: ThemeMode): void { + localStorage.setItem(STORAGE_KEY, mode); + applyToDOM(mode); +} + export function loadSavedTheme(): void { - applyTheme(getSavedTheme()); + applyToDOM(resolveTheme()); + + if (mql) { + const onSystemChange = (e: MediaQueryListEvent) => { + const hasOverride = + localStorage.getItem(STORAGE_KEY) === "light" || + localStorage.getItem(STORAGE_KEY) === "dark"; + if (!hasOverride) applyToDOM(e.matches ? "dark" : "light"); + }; + if ("addEventListener" in mql) { + mql.addEventListener("change", onSystemChange); + } else if (typeof (mql as any).addListener === "function") { + (mql as any).addListener(onSystemChange); + } + } + + window.addEventListener("storage", (e) => { + if (e.key === STORAGE_KEY) applyToDOM(resolveTheme()); + }); } + export function toggleTheme(): void { - const next = getSavedTheme() === "dark" ? "light" : "dark"; - applyTheme(next); + const next = resolveTheme() === "dark" ? "light" : "dark"; + localStorage.setItem(STORAGE_KEY, next); + applyToDOM(next); } - -themeToggleButton.addEventListener("click", toggleTheme); +themeToggleButton?.addEventListener("click", toggleTheme);