Add persistent dark theme toggle
This commit is contained in:
@@ -24,6 +24,7 @@ const sourceTitle = document.querySelector("#sourceTitle");
|
||||
const sourceList = document.querySelector("#sourceList");
|
||||
const sourceCloseButton = document.querySelector("#sourceCloseButton");
|
||||
const settingsButton = document.querySelector("#settingsButton");
|
||||
const themeToggle = document.querySelector("#themeToggle");
|
||||
const settingsModal = document.querySelector("#settingsModal");
|
||||
const settingsCloseButton = document.querySelector("#settingsCloseButton");
|
||||
const databaseModeNote = document.querySelector("#databaseModeNote");
|
||||
@@ -120,6 +121,7 @@ const productFieldMap = {
|
||||
};
|
||||
|
||||
await loadStatus();
|
||||
loadTheme();
|
||||
renderFields();
|
||||
renderTableHeader();
|
||||
setTableWidth();
|
||||
@@ -167,6 +169,7 @@ sourceModal.addEventListener("click", (event) => {
|
||||
if (event.target === sourceModal) closeSourceCandidates();
|
||||
});
|
||||
settingsButton.addEventListener("click", openSettings);
|
||||
themeToggle.addEventListener("click", toggleTheme);
|
||||
settingsCloseButton.addEventListener("click", closeSettings);
|
||||
settingsModal.addEventListener("click", (event) => {
|
||||
if (event.target === settingsModal) closeSettings();
|
||||
@@ -823,6 +826,19 @@ function openSettings() {
|
||||
settingsModal.hidden = false;
|
||||
}
|
||||
|
||||
function loadTheme() {
|
||||
const isDark = localStorage.getItem("catalog-maker:theme") === "dark";
|
||||
document.documentElement.classList.toggle("dark", isDark);
|
||||
themeToggle.textContent = isDark ? "Light theme" : "Dark theme";
|
||||
themeToggle.setAttribute("aria-pressed", String(isDark));
|
||||
}
|
||||
|
||||
function toggleTheme() {
|
||||
const isDark = !document.documentElement.classList.contains("dark");
|
||||
localStorage.setItem("catalog-maker:theme", isDark ? "dark" : "light");
|
||||
loadTheme();
|
||||
}
|
||||
|
||||
function closeSettings() {
|
||||
settingsModal.hidden = true;
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
<button class="action-button primary" type="button">Show menu (20)</button>
|
||||
<button class="action-button" type="button">Scraper - 03</button>
|
||||
<button class="action-button" type="button">BG remover - 04</button>
|
||||
<button class="action-button" id="themeToggle" type="button" aria-pressed="false">Dark theme</button>
|
||||
<button class="action-button" id="settingsButton" type="button">Settings</button>
|
||||
</aside>
|
||||
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
@@ -21,6 +21,10 @@
|
||||
color-scheme: light;
|
||||
}
|
||||
|
||||
html.dark {
|
||||
color-scheme: dark;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
@@ -142,4 +146,42 @@
|
||||
.product-panel { @apply pt-0; }
|
||||
.table-wrap { @apply max-h-[70vh]; }
|
||||
}
|
||||
|
||||
html.dark body { @apply bg-slate-950 text-slate-100; }
|
||||
html.dark .control-panel { @apply bg-slate-950; }
|
||||
html.dark .product-panel { @apply bg-slate-800; }
|
||||
html.dark .data-panel { @apply bg-slate-950; }
|
||||
html.dark .field-label { @apply border-slate-700 bg-slate-800 text-slate-200; }
|
||||
html.dark .field-value { @apply border-slate-700 bg-slate-900 text-slate-100; }
|
||||
html.dark .variant-table th { @apply border-slate-700 bg-slate-800 text-slate-100; }
|
||||
html.dark .variant-table td { @apply border-slate-700 bg-slate-900 text-slate-200; }
|
||||
html.dark .variant-table tr:nth-child(even) td { @apply bg-slate-800; }
|
||||
html.dark .variant-table tr:hover td { @apply bg-slate-700; }
|
||||
html.dark .arrow-button,
|
||||
html.dark .action-button,
|
||||
html.dark .input-like { @apply border-slate-600 bg-slate-800 text-slate-100; }
|
||||
html.dark .arrow-button:hover:not(:disabled),
|
||||
html.dark .action-button:hover:not(:disabled) { @apply border-slate-400 bg-slate-700; }
|
||||
html.dark #scanInput { @apply bg-slate-700 placeholder:text-slate-400; }
|
||||
html.dark .settings-dialog,
|
||||
html.dark .suggested-dialog,
|
||||
html.dark .source-dialog { @apply border-slate-700 bg-slate-900; }
|
||||
html.dark .suggested-header { @apply border-slate-700 bg-slate-800; }
|
||||
html.dark .suggested-header h2,
|
||||
html.dark .settings-group legend,
|
||||
html.dark .settings-option,
|
||||
html.dark .settings-field { @apply text-slate-100; }
|
||||
html.dark .settings-group { @apply border-slate-700; }
|
||||
html.dark .settings-field input { @apply border-slate-600 bg-slate-800 text-slate-100; }
|
||||
html.dark .modal-close,
|
||||
html.dark .settings-test-button,
|
||||
html.dark .suggested-pick,
|
||||
html.dark .source-row-action,
|
||||
html.dark .source-picture-action { @apply border-slate-600 bg-slate-800 text-slate-100 hover:bg-slate-700; }
|
||||
html.dark .source-section { @apply border-slate-700; }
|
||||
html.dark .source-section-header { @apply border-slate-700 bg-slate-800 text-slate-100; }
|
||||
html.dark .source-row { @apply border-slate-700 bg-slate-900 text-slate-100 hover:bg-slate-800; }
|
||||
html.dark .suggested-row,
|
||||
html.dark .picture-candidate { @apply border-slate-700; }
|
||||
html.dark .suggested-row:nth-child(even) { @apply bg-slate-800; }
|
||||
}
|
||||
|
||||
@@ -30,3 +30,15 @@ test("catalog maker remains usable on a narrow viewport", async ({ page }) => {
|
||||
await expect(page.locator("#settingsButton")).toBeVisible();
|
||||
await page.screenshot({ path: "test-results/catalog-maker-mobile.png", fullPage: true });
|
||||
});
|
||||
|
||||
test("theme toggle switches and persists dark mode", async ({ page }) => {
|
||||
await page.goto("/");
|
||||
await expect(page.locator("html")).not.toHaveClass(/dark/);
|
||||
|
||||
await page.locator("#themeToggle").click();
|
||||
await expect(page.locator("html")).toHaveClass(/dark/);
|
||||
await expect(page.locator("#themeToggle")).toHaveText("Light theme");
|
||||
|
||||
await page.reload();
|
||||
await expect(page.locator("html")).toHaveClass(/dark/);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user