From 4b7bb41fd75e7bac177131d14ebc03d86c7bf216 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=B8=D0=BA=D1=82=D0=BE=D1=80?= <78488229+viktor138irk@users.noreply.github.com> Date: Thu, 7 May 2026 20:54:51 +0900 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D1=8E?= =?UTF-8?q?=D1=87=D0=B0=D1=82=D0=B5=D0=BB=D1=8C=20=D1=82=D0=B5=D0=BC=20?= =?UTF-8?q?=D0=B1=D1=8B=D0=BB=20=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/static/panel.js | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/web/static/panel.js b/web/static/panel.js index c6b0279..39897c5 100644 --- a/web/static/panel.js +++ b/web/static/panel.js @@ -6,6 +6,45 @@ function qs(selector, root = document) { return root.querySelector(selector); } function qsa(selector, root = document) { return Array.from(root.querySelectorAll(selector)); } + function ensureThemeStyles() { + if (qs('link[data-virtuality-themes="1"]')) return; + const link = document.createElement('link'); + link.rel = 'stylesheet'; + link.href = '/static/themes.css'; + link.dataset.virtualityThemes = '1'; + document.head.appendChild(link); + } + + function getTheme() { + return localStorage.getItem('virtualityTheme') || 'neon'; + } + + function applyTheme(theme) { + const selected = theme === 'macos' ? 'macos' : 'neon'; + document.documentElement.dataset.theme = selected; + localStorage.setItem('virtualityTheme', selected); + qsa('[data-theme-select]').forEach((btn) => { + btn.classList.toggle('is-active', btn.dataset.themeSelect === selected); + }); + } + + function wireThemeSwitcher() { + ensureThemeStyles(); + const nav = qs('.v-nav'); + if (!nav || qs('.theme-switcher')) { + applyTheme(getTheme()); + return; + } + const switcher = document.createElement('div'); + switcher.className = 'theme-switcher'; + switcher.innerHTML = '
Тема
'; + nav.appendChild(switcher); + qsa('[data-theme-select]', switcher).forEach((btn) => { + btn.addEventListener('click', () => applyTheme(btn.dataset.themeSelect)); + }); + applyTheme(getTheme()); + } + function activeSidebar(pathname = window.location.pathname) { qsa('.v-nav a').forEach((item) => { const url = new URL(item.href, window.location.href); @@ -65,6 +104,7 @@ } function initPanel() { + wireThemeSwitcher(); wireNavGroups(); wireMobileMenu(); activeSidebar(); @@ -72,6 +112,7 @@ } document.addEventListener('DOMContentLoaded', initPanel); + applyTheme(getTheme()); })(); /* Virtuality live status + toast layer */