From bf2d86329b48b44c4d921bae6c525eabca58ea4f Mon Sep 17 00:00:00 2001 From: rajch_ales Date: Wed, 5 Aug 2026 15:59:16 +0200 Subject: [PATCH] Add configurable sidebar contrast settings --- public/app.js | 24 ++++++++++++++++++++++++ public/app.ts | 27 +++++++++++++++++++++++++++ public/index.html | 21 +++++++++++++++++++++ public/styles.css | 2 +- src/tailwind.css | 13 +++++++++++++ tests/ui/catalog-maker.smoke.spec.ts | 12 +++++++++--- 6 files changed, 95 insertions(+), 4 deletions(-) diff --git a/public/app.js b/public/app.js index ecda578..5211152 100644 --- a/public/app.js +++ b/public/app.js @@ -48,6 +48,8 @@ const localDbFields = document.querySelector("#localDbFields"); const localDbInputs = document.querySelectorAll("#localDbFields input"); const testLocalDbButton = document.querySelector("#testLocalDbButton"); const localDbTestResult = document.querySelector("#localDbTestResult"); +const lightContrastSelect = document.querySelector("#lightContrastSelect"); +const darkContrastSelect = document.querySelector("#darkContrastSelect"); const nativeFetch = window.fetch.bind(window); window.fetch = (input, init = {}) => { const url = typeof input === "string" ? input : input.url; @@ -128,6 +130,7 @@ const productFieldMap = { }; await loadStatus(); loadTheme(); +loadAppearance(); renderFields(); renderTableHeader(); setTableWidth(); @@ -210,6 +213,8 @@ for (const input of transactionModeInputs) for (const input of localDbInputs) input.addEventListener("change", saveLocalDbSettings); testLocalDbButton.addEventListener("click", testLocalDbConnection); +lightContrastSelect.addEventListener("change", saveAppearance); +darkContrastSelect.addEventListener("change", saveAppearance); loadDatabaseMode(); syncSidebarForViewport(); window.matchMedia("(min-width: 981px)").addEventListener("change", syncSidebarForViewport); @@ -864,6 +869,25 @@ function loadTheme() { themeToggle.querySelector("span").textContent = isDark ? "Light theme" : "Dark theme"; themeToggle.setAttribute("aria-pressed", String(isDark)); } +function loadAppearance() { + const settings = JSON.parse(localStorage.getItem("catalog-maker:appearance") || "{}"); + lightContrastSelect.value = settings.lightContrast || "medium"; + darkContrastSelect.value = settings.darkContrast || "medium"; + applyAppearance(); +} +function saveAppearance() { + localStorage.setItem("catalog-maker:appearance", JSON.stringify({ + lightContrast: lightContrastSelect.value, + darkContrast: darkContrastSelect.value, + })); + applyAppearance(); +} +function applyAppearance() { + const root = document.documentElement; + root.classList.remove("contrast-light-low", "contrast-light-medium", "contrast-light-high", "contrast-dark-low", "contrast-dark-medium", "contrast-dark-high"); + root.classList.add(`contrast-light-${lightContrastSelect.value || "medium"}`); + root.classList.add(`contrast-dark-${darkContrastSelect.value || "medium"}`); +} function toggleTheme() { const isDark = !document.documentElement.classList.contains("dark"); localStorage.setItem("catalog-maker:theme", isDark ? "dark" : "light"); diff --git a/public/app.ts b/public/app.ts index 840d6c2..7daebc7 100644 --- a/public/app.ts +++ b/public/app.ts @@ -48,6 +48,8 @@ const localDbFields = document.querySelector("#localDbFields"); const localDbInputs = document.querySelectorAll("#localDbFields input"); const testLocalDbButton = document.querySelector("#testLocalDbButton"); const localDbTestResult = document.querySelector("#localDbTestResult"); +const lightContrastSelect = document.querySelector("#lightContrastSelect"); +const darkContrastSelect = document.querySelector("#darkContrastSelect"); const nativeFetch = window.fetch.bind(window); window.fetch = (input, init = {}) => { @@ -134,6 +136,7 @@ const productFieldMap = { await loadStatus(); loadTheme(); +loadAppearance(); renderFields(); renderTableHeader(); setTableWidth(); @@ -209,6 +212,8 @@ for (const input of permissionInputs) input.addEventListener("change", saveSetti for (const input of transactionModeInputs) input.addEventListener("change", saveSettings); for (const input of localDbInputs) input.addEventListener("change", saveLocalDbSettings); testLocalDbButton.addEventListener("click", testLocalDbConnection); +lightContrastSelect.addEventListener("change", saveAppearance); +darkContrastSelect.addEventListener("change", saveAppearance); loadDatabaseMode(); syncSidebarForViewport(); @@ -954,6 +959,28 @@ function loadTheme() { themeToggle.setAttribute("aria-pressed", String(isDark)); } +function loadAppearance() { + const settings = JSON.parse(localStorage.getItem("catalog-maker:appearance") || "{}"); + lightContrastSelect.value = settings.lightContrast || "medium"; + darkContrastSelect.value = settings.darkContrast || "medium"; + applyAppearance(); +} + +function saveAppearance() { + localStorage.setItem("catalog-maker:appearance", JSON.stringify({ + lightContrast: lightContrastSelect.value, + darkContrast: darkContrastSelect.value, + })); + applyAppearance(); +} + +function applyAppearance() { + const root = document.documentElement; + root.classList.remove("contrast-light-low", "contrast-light-medium", "contrast-light-high", "contrast-dark-low", "contrast-dark-medium", "contrast-dark-high"); + root.classList.add(`contrast-light-${lightContrastSelect.value || "medium"}`); + root.classList.add(`contrast-dark-${darkContrastSelect.value || "medium"}`); +} + function toggleTheme() { const isDark = !document.documentElement.classList.contains("dark"); localStorage.setItem("catalog-maker:theme", isDark ? "dark" : "light"); diff --git a/public/index.html b/public/index.html index 24f94f4..e44c0e9 100644 --- a/public/index.html +++ b/public/index.html @@ -176,6 +176,27 @@

Local test database selected.

+
+ Appearance + + +

Controls the contrast of the left sidebar and its controls.

+
+
Access permissions