From b8a2421f433f7692d2e0568eeebffba5481e1dfc Mon Sep 17 00:00:00 2001
From: Scott McKendry <39483124+scottmckendry@users.noreply.github.com>
Date: Mon, 3 Feb 2025 12:22:49 +1300
Subject: [PATCH] feat(ui): add theme toggle button
---
.air.toml | 2 +-
public/css/style.css | 123 +++++++++++++++++++++-----------------
public/js/theme_toggle.js | 24 ++++++++
views/index.html | 25 +++++---
4 files changed, 111 insertions(+), 63 deletions(-)
create mode 100644 public/js/theme_toggle.js
diff --git a/.air.toml b/.air.toml
index 787fedc..56eb24a 100644
--- a/.air.toml
+++ b/.air.toml
@@ -14,7 +14,7 @@ exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
-include_ext = ["go", "html", "css", "toml"]
+include_ext = ["go", "html", "css", "toml", "js"]
kill_delay = "0s"
log = "build-errors.log"
send_interrupt = false
diff --git a/public/css/style.css b/public/css/style.css
index 8033438..6a42e82 100644
--- a/public/css/style.css
+++ b/public/css/style.css
@@ -1,14 +1,41 @@
+:root {
+ color-scheme: light dark;
+ --bg-color: #ffffff;
+ --text-color: #333;
+ --header-bg: #37474f;
+ --card-bg: #ffffff;
+ --card-shadow: rgba(0, 0, 0, 0.2);
+ --hr-color: #eee;
+ --input-border: #ccc;
+ --modal-bg: white;
+}
+
+:root[theme="dark"] {
+ --bg-color: #1b1a19;
+ --text-color: #fff;
+ --header-bg: #323130;
+ --card-bg: #323130;
+ --card-shadow: rgba(0, 0, 0, 0.2);
+ --hr-color: rgba(255, 255, 255, 0.1);
+ --input-border: #fff;
+ --modal-bg: #323130;
+}
+
body {
- color: #333;
+ color: var(--text-color);
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
font-size: 14px;
margin: 0;
+ background-color: var(--bg-color);
+ transition:
+ background-color 0.3s,
+ color 0.3s;
}
header {
position: sticky;
top: 0;
- background-color: #37474f;
+ background-color: var(--header-bg);
color: #fff;
padding: 10px;
display: flex;
@@ -44,6 +71,27 @@ header h1 {
filter: grayscale(100%) brightness(0) invert(1);
}
+.theme-toggle {
+ border: none;
+ border-radius: 50%;
+ padding: 8px;
+ background: transparent;
+ color: #fff;
+ cursor: pointer;
+ margin-right: 10px;
+ width: 35px;
+ height: 35px;
+}
+
+.theme-toggle:hover {
+ background-color: rgba(255, 255, 255, 0.1);
+}
+
+.header-buttons {
+ display: flex;
+ align-items: center;
+}
+
#spinner {
position: fixed;
width: 100%;
@@ -76,14 +124,15 @@ header h1 {
.card {
padding: 10px;
border-radius: 5px;
- box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 0 10px var(--card-shadow);
+ background-color: var(--card-bg);
flex: 0 1 300px;
min-width: 350px;
max-width: 650px;
}
hr {
- border: 1px solid #eee;
+ border: 1px solid var(--hr-color);
}
.card-title {
@@ -182,13 +231,14 @@ hr {
width: 100%;
padding: 5px;
font-size: 14px;
- border: 1px solid #ccc;
+ border: 1px solid var(--input-border);
border-radius: 5px;
box-sizing: border-box;
+ background-color: var(--card-bg);
+ color: var(--text-color);
}
#modal {
- /* Underlay covers entire screen. */
position: fixed;
top: 0px;
bottom: 0px;
@@ -196,21 +246,15 @@ hr {
right: 0px;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1000;
-
- /* Flexbox centers the .modal-content vertically and horizontally */
display: flex;
flex-direction: column;
align-items: center;
-
- /* Animate when opening */
animation-name: fadeIn;
animation-duration: 150ms;
animation-timing-function: ease;
}
#modal > .modal-underlay {
- /* underlay takes up the entire viewport. This is only
- required if you want to click to dismiss the popup */
position: absolute;
z-index: -1;
top: 0px;
@@ -220,35 +264,26 @@ hr {
}
#modal > .modal-content {
- /* Position visible dialog near the top of the window */
margin-top: 10vh;
-
- /* Sizing for visible dialog */
width: 80%;
max-width: 600px;
-
- /* Display properties for visible dialog*/
border: solid 1px #999;
border-radius: 8px;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.3);
- background-color: white;
+ background-color: var(--modal-bg);
padding: 20px;
-
- /* Animate when opening */
animation-name: zoomIn;
animation-duration: 150ms;
animation-timing-function: ease;
}
#modal.closing {
- /* Animate when closing */
animation-name: fadeOut;
animation-duration: 150ms;
animation-timing-function: ease;
}
#modal.closing > .modal-content {
- /* Animate when closing */
animation-name: zoomOut;
animation-duration: 150ms;
animation-timing-function: ease;
@@ -259,8 +294,10 @@ hr {
padding: 5px;
font-size: 16px;
margin-bottom: 10px;
- border: 1px solid #ccc;
+ border: 1px solid var(--input-border);
border-radius: 5px;
+ background-color: var(--card-bg);
+ color: var(--text-color);
}
@keyframes fadeIn {
@@ -309,36 +346,14 @@ hr {
}
@media (prefers-color-scheme: dark) {
- body {
- background-color: #1b1a19;
- color: #fff;
- }
-
- header {
- background-color: #323130;
- }
-
- .card {
- background-color: #323130;
- }
-
- hr {
- border: 1px solid rgba(255, 255, 255, 0.1);
- }
-
- #modal > .modal-content {
- background-color: #323130;
- }
-
- #modal input {
- border: 1px solid #fff;
- background-color: #323130;
- color: #fff;
- }
-
- .service-entry input {
- border: 1px solid #fff;
- background-color: #323130;
- color: #fff;
+ :root:not([theme="light"]) {
+ --bg-color: #1b1a19;
+ --text-color: #fff;
+ --header-bg: #323130;
+ --card-bg: #323130;
+ --card-shadow: rgba(0, 0, 0, 0.2);
+ --hr-color: rgba(255, 255, 255, 0.1);
+ --input-border: #fff;
+ --modal-bg: #323130;
}
}
diff --git a/public/js/theme_toggle.js b/public/js/theme_toggle.js
new file mode 100644
index 0000000..127d01b
--- /dev/null
+++ b/public/js/theme_toggle.js
@@ -0,0 +1,24 @@
+const getPreferredTheme = () => {
+ return window.matchMedia("(prefers-color-scheme: dark)").matches
+ ? "dark"
+ : "light";
+};
+
+window.toggleTheme = () => {
+ const current = document.documentElement.getAttribute("theme");
+ const newTheme = current === "dark" ? "light" : "dark";
+ document.documentElement.setAttribute("theme", newTheme);
+ updateToggleIcon(newTheme);
+};
+
+const updateToggleIcon = (theme) => {
+ const icon = document.querySelector(".theme-toggle i");
+ if (icon) {
+ icon.className = theme === "dark" ? "nf nf-fa-sun" : "nf nf-fa-moon";
+ }
+};
+
+document.addEventListener("DOMContentLoaded", () => {
+ document.documentElement.setAttribute("theme", getPreferredTheme());
+ updateToggleIcon(getPreferredTheme());
+});
diff --git a/views/index.html b/views/index.html
index 3547cd4..875c01b 100644
--- a/views/index.html
+++ b/views/index.html
@@ -18,6 +18,7 @@
href="https://www.nerdfonts.com/assets/css/webfont.css"
rel="stylesheet"
/>
+
@@ -28,14 +29,22 @@