add color theme option

This commit is contained in:
Arthur Lu 2024-06-14 06:17:15 +00:00
parent d2cfbdb2a2
commit d3281fc27f
8 changed files with 115 additions and 25 deletions

View File

@ -1,15 +1,19 @@
:root { :root {
--nav-transition-speed: 250ms;
}
@media screen and (prefers-color-scheme: dark) {
:root, :root.dark-theme {
--nav-bg-color: black; --nav-bg-color: black;
--nav-text-color: white; --nav-text-color: white;
--nav-header-bg-color: #0f0; --nav-header-bg-color: #0f0;
--nav-header-text-color: black; --nav-header-text-color: black;
--nav-link-active-text-color: white; --nav-link-active-text-color: white;
--nav-link-active-bg-color: var(--main-bg-color, #404040); --nav-link-active-bg-color: var(--main-bg-color, #404040);
--nav-transition-speed: 250ms;
}
@media screen and (prefers-color-scheme: light) { }
:root {
:root.light-theme {
--nav-bg-color: black; --nav-bg-color: black;
--nav-text-color: white; --nav-text-color: white;
--nav-header-bg-color: #0f0; --nav-header-bg-color: #0f0;
@ -19,6 +23,27 @@
} }
} }
@media screen and (prefers-color-scheme: light) {
:root, :root.light-theme {
--nav-bg-color: black;
--nav-text-color: white;
--nav-header-bg-color: #0f0;
--nav-header-text-color: black;
--nav-link-active-text-color: black;
--nav-link-active-bg-color: var(--main-bg-color, white);
}
:root.dark-theme {
--nav-bg-color: black;
--nav-text-color: white;
--nav-header-bg-color: #0f0;
--nav-header-text-color: black;
--nav-link-active-text-color: white;
--nav-link-active-bg-color: var(--main-bg-color, #404040);
}
}
header { header {
display: grid; display: grid;
align-items: center; align-items: center;

View File

@ -3,16 +3,19 @@
--positive-color: #0f0; --positive-color: #0f0;
--highlight-color: yellow; --highlight-color: yellow;
--lightbg-text-color: black; --lightbg-text-color: black;
}
@media screen and (prefers-color-scheme: dark) {
:root, :root.dark-theme {
--main-bg-color: #404040; --main-bg-color: #404040;
--main-text-color: white; --main-text-color: white;
--main-card-bg-color: #202020; --main-card-bg-color: #202020;
--main-card-box-shadow: 0 2px 5px 0 rgb(0 0 0 / 80%), 0 2px 10px 0 rgb(0 0 0 / 80%); --main-card-box-shadow: 0 2px 5px 0 rgb(0 0 0 / 80%), 0 2px 10px 0 rgb(0 0 0 / 80%);
--main-table-header-bg-color: black; --main-table-header-bg-color: black;
--main-input-bg-color: #404040; --main-input-bg-color: #404040;
} }
@media screen and (prefers-color-scheme: light) { :root.light-theme {
:root {
--main-bg-color: white; --main-bg-color: white;
--main-text-color: black; --main-text-color: black;
--main-card-bg-color: white; --main-card-bg-color: white;
@ -22,6 +25,26 @@
} }
} }
@media screen and (prefers-color-scheme: light) {
:root, :root.light-theme {
--main-bg-color: white;
--main-text-color: black;
--main-card-bg-color: white;
--main-card-box-shadow: 0 2px 5px 0 rgb(0 0 0 / 20%), 0 2px 10px 0 rgb(0 0 0 / 20%);
--main-table-header-bg-color: #808080;
--main-input-bg-color: white;
}
:root.dark-theme {
--main-bg-color: #404040;
--main-text-color: white;
--main-card-bg-color: #202020;
--main-card-box-shadow: 0 2px 5px 0 rgb(0 0 0 / 80%), 0 2px 10px 0 rgb(0 0 0 / 80%);
--main-table-header-bg-color: black;
--main-input-bg-color: #404040;
}
}
html { html {
box-sizing: border-box; box-sizing: border-box;
} }
@ -115,8 +138,7 @@ hr, * {
.w3-select, select { .w3-select, select {
padding: 8px; padding: 8px;
-moz-appearance: none; appearance: none;
-webkit-appearance: none;
appearance: none; appearance: none;
appearance: none; appearance: none;
background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E:root%7Bcolor:%23fff%7D@media (prefers-color-scheme:light)%7B:root%7Bcolor:%23000%7D%7D%3C/style%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.707 14.707a1 1 0 01-1.414 0l-5-5a1 1 0 011.414-1.414L12 12.586l4.293-4.293a1 1 0 111.414 1.414l-5 5z' fill='currentColor'/%3E%3C/svg%3E"); background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cstyle%3E:root%7Bcolor:%23fff%7D@media (prefers-color-scheme:light)%7B:root%7Bcolor:%23000%7D%7D%3C/style%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M12.707 14.707a1 1 0 01-1.414 0l-5-5a1 1 0 011.414-1.414L12 12.586l4.293-4.293a1 1 0 111.414 1.414l-5 5z' fill='currentColor'/%3E%3C/svg%3E");

View File

@ -1,5 +1,5 @@
import { dialog } from "./dialog.js"; import { dialog } from "./dialog.js";
import { requestAPI, goToPage, getCookie, setTitleAndHeader } from "./utils.js"; import { requestAPI, goToPage, getCookie, setTitleAndHeader, setAppearance } from "./utils.js";
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
@ -21,6 +21,7 @@ const prefixes = {
}; };
async function init () { async function init () {
setAppearance();
setTitleAndHeader(); setTitleAndHeader();
const cookie = document.cookie; const cookie = document.cookie;
if (cookie === "") { if (cookie === "") {

View File

@ -1,13 +1,14 @@
import { requestPVE, requestAPI, goToPage, setTitleAndHeader } from "./utils.js"; import { requestPVE, requestAPI, goToPage, setTitleAndHeader, setAppearance } from "./utils.js";
import { alert, dialog } from "./dialog.js"; import { alert, dialog } from "./dialog.js";
import { setupClientSync } from "./clientsync.js"; import { setupClientSync } from "./clientsync.js";
import wf_align from "../modules/wfa.js"; import wfAlign from "../modules/wfa.js";
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
let instances = []; let instances = [];
async function init () { async function init () {
setAppearance();
setTitleAndHeader(); setTitleAndHeader();
const cookie = document.cookie; const cookie = document.cookie;
if (cookie === "") { if (cookie === "") {
@ -78,9 +79,9 @@ async function populateInstances () {
}; };
criteria = (a, b) => { criteria = (a, b) => {
// lower is better // lower is better
const aAlign = wf_align(a.name.toLowerCase(), searchQuery.toLowerCase(), penalties); const aAlign = wfAlign(a.name.toLowerCase(), searchQuery.toLowerCase(), penalties);
const aScore = aAlign.score / a.name.length; const aScore = aAlign.score / a.name.length;
const bAlign = wf_align(b.name.toLowerCase(), searchQuery.toLowerCase(), penalties); const bAlign = wfAlign(b.name.toLowerCase(), searchQuery.toLowerCase(), penalties);
const bScore = bAlign.score / b.name.length; const bScore = bAlign.score / b.name.length;
if (aScore === bScore) { if (aScore === bScore) {
return a.vmid > b.vmid ? 1 : -1; return a.vmid > b.vmid ? 1 : -1;

View File

@ -1,9 +1,10 @@
import { requestTicket, goToPage, deleteAllCookies, requestPVE, setTitleAndHeader } from "./utils.js"; import { requestTicket, goToPage, deleteAllCookies, requestPVE, setTitleAndHeader, setAppearance } from "./utils.js";
import { alert } from "./dialog.js"; import { alert } from "./dialog.js";
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
async function init () { async function init () {
setAppearance();
setTitleAndHeader(); setTitleAndHeader();
await deleteAllCookies(); await deleteAllCookies();
const formSubmitButton = document.querySelector("#submit"); const formSubmitButton = document.querySelector("#submit");

View File

@ -1,8 +1,9 @@
import { setTitleAndHeader } from "./utils.js"; import { setTitleAndHeader, setAppearance } from "./utils.js";
window.addEventListener("DOMContentLoaded", init); window.addEventListener("DOMContentLoaded", init);
function init () { function init () {
setAppearance();
setTitleAndHeader(); setTitleAndHeader();
const scheme = localStorage.getItem("sync-scheme"); const scheme = localStorage.getItem("sync-scheme");
if (scheme) { if (scheme) {
@ -16,6 +17,10 @@ function init () {
if (search) { if (search) {
document.querySelector(`#search-${search}`).checked = true; document.querySelector(`#search-${search}`).checked = true;
} }
const theme = localStorage.getItem("appearance-theme");
if (theme) {
document.querySelector("#appearance-theme").value = theme;
}
document.querySelector("#settings").addEventListener("submit", handleSaveSettings, false); document.querySelector("#settings").addEventListener("submit", handleSaveSettings, false);
} }
@ -25,5 +30,6 @@ function handleSaveSettings (event) {
localStorage.setItem("sync-scheme", form.get("sync-scheme")); localStorage.setItem("sync-scheme", form.get("sync-scheme"));
localStorage.setItem("sync-rate", form.get("sync-rate")); localStorage.setItem("sync-rate", form.get("sync-rate"));
localStorage.setItem("search-criteria", form.get("search-criteria")); localStorage.setItem("search-criteria", form.get("search-criteria"));
localStorage.setItem("appearance-theme", form.get("appearance-theme"));
window.location.reload(); window.location.reload();
} }

View File

@ -267,3 +267,23 @@ export function setTitleAndHeader () {
document.title = `${organization} - dashboard`; document.title = `${organization} - dashboard`;
document.querySelector("h1").innerText = organization; document.querySelector("h1").innerText = organization;
} }
export function setAppearance () {
let theme = localStorage.getItem("appearance-theme");
if (!theme) {
theme = "auto";
localStorage.setItem("appearance-theme", "auto");
}
if (theme === "auto") {
document.querySelector(":root").classList.remove("dark-theme", "light-theme");
}
else if (theme === "dark") {
document.querySelector(":root").classList.remove("light-theme");
document.querySelector(":root").classList.add("dark-theme");
}
else if (theme === "light") {
document.querySelector(":root").classList.add("light-theme");
document.querySelector(":root").classList.remove("dark-theme");
}
}

View File

@ -6,6 +6,7 @@
<title>proxmox - dashboard</title> <title>proxmox - dashboard</title>
<link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml"> <link rel="icon" href="images/favicon.svg" sizes="any" type="image/svg+xml">
<link rel="stylesheet" href="w3.css"> <link rel="stylesheet" href="w3.css">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/style.css">
<link rel="stylesheet" href="css/nav.css"> <link rel="stylesheet" href="css/nav.css">
<link rel="stylesheet" href="css/form.css"> <link rel="stylesheet" href="css/form.css">
@ -75,6 +76,19 @@
<p>Sorts by best matching to worst matching.</p> <p>Sorts by best matching to worst matching.</p>
</fieldset> </fieldset>
</div> </div>
<div class="w3-card w3-padding">
<h3>Appearance</h3>
<fieldset>
<label>
Theme
<select class="w3-select w3-border" id="appearance-theme" name="appearance-theme" style="width: fit-content; padding-right: 24px;">
<option value="auto">Auto</option>
<option value="dark">Dark</option>
<option value="light">Light</option>
</select>
</label>
</fieldset>
</div>
<div class="w3-container w3-center" id="form-actions"> <div class="w3-container w3-center" id="form-actions">
<button class="w3-button w3-margin" id="save" type="submit">SAVE</button> <button class="w3-button w3-margin" id="save" type="submit">SAVE</button>
</div> </div>