From b5fb1d1190eeda90057cf02d0d4fd9e86b74a6f8 Mon Sep 17 00:00:00 2001 From: juvdiaz Date: Fri, 29 May 2026 11:12:20 -0600 Subject: [PATCH] Fixing theme button --- apps/demos-static/public/shared.css | 139 ++++++++++++++ apps/demos-static/public/theme.js | 31 +-- apps/website/blog.php | 2 +- apps/website/cv-theme.js | 20 +- apps/website/cv.php | 2 +- apps/website/index.php | 2 +- apps/website/partials/translation_ui.php | 2 +- apps/website/styles.css | 232 +++++++++++++++++++++++ 8 files changed, 409 insertions(+), 21 deletions(-) diff --git a/apps/demos-static/public/shared.css b/apps/demos-static/public/shared.css index f2ba8aa..68e0876 100644 --- a/apps/demos-static/public/shared.css +++ b/apps/demos-static/public/shared.css @@ -385,3 +385,142 @@ pre { flex-direction: column; } } + +body.theme-dark { + background: #000; + color: #39ff14; + font-family: "Courier New", "Lucida Console", Monaco, monospace; + font-size: 1rem; + line-height: 1.56; +} + +body.theme-light { + background: #fffff0; + color: #1b1610; + font-family: "Brush Script MT", "Segoe Script", "Snell Roundhand", "Apple Chancery", cursive; + font-size: 1.12rem; + line-height: 1.68; +} + +body.theme-dark .topline a, +body.theme-dark .site-theme-toolbar, +body.theme-dark .kicker, +body.theme-dark h1, +body.theme-dark h2, +body.theme-dark h3, +body.theme-dark label, +body.theme-dark strong, +body.theme-dark a { + color: #7cff7c; + font-family: inherit; +} + +body.theme-dark p, +body.theme-dark span, +body.theme-dark li, +body.theme-dark .note, +body.theme-dark .catalog-card p, +body.theme-dark .result-row span, +body.theme-dark .stats span { + color: #39ff14; +} + +body.theme-dark .hero, +body.theme-dark .panel, +body.theme-dark .catalog-card, +body.theme-dark .drop-zone, +body.theme-dark .result-row, +body.theme-dark .stats span { + background: #000; + border-color: #1fbf3a; + color: #39ff14; + box-shadow: 0 0 16px rgba(57, 255, 20, 0.16); +} + +body.theme-dark button, +body.theme-dark .download-link, +body.theme-dark .site-theme-option { + background: #000; + border: 1px solid #39ff14; + color: #39ff14; + font-family: inherit; +} + +body.theme-dark button:hover, +body.theme-dark .download-link:hover, +body.theme-dark .site-theme-option.is-active { + background: #062b06; + color: #b6ffb6; +} + +body.theme-dark select, +body.theme-dark input, +body.theme-dark textarea, +body.theme-dark canvas, +body.theme-dark .output, +body.theme-dark pre { + background: #000; + border-color: #1fbf3a; + color: #39ff14; + font-family: inherit; +} + +body.theme-light .topline a, +body.theme-light .site-theme-toolbar, +body.theme-light .kicker, +body.theme-light h1, +body.theme-light h2, +body.theme-light h3, +body.theme-light label, +body.theme-light strong, +body.theme-light a, +body.theme-light p, +body.theme-light span, +body.theme-light li, +body.theme-light .note, +body.theme-light .catalog-card p, +body.theme-light .result-row span, +body.theme-light .stats span { + color: #1b1610; + font-family: inherit; +} + +body.theme-light .hero, +body.theme-light .panel, +body.theme-light .catalog-card, +body.theme-light .drop-zone, +body.theme-light .result-row, +body.theme-light .stats span { + background: #fffff0; + border-color: #1b1610; + color: #1b1610; + box-shadow: none; +} + +body.theme-light button, +body.theme-light .download-link, +body.theme-light .site-theme-option { + background: #fffff0; + border: 1px solid #1b1610; + color: #1b1610; + font-family: inherit; +} + +body.theme-light button:hover, +body.theme-light .download-link:hover, +body.theme-light .site-theme-option.is-active { + background: #1b1610; + color: #fffff0; +} + +body.theme-light select, +body.theme-light input, +body.theme-light textarea, +body.theme-light canvas, +body.theme-light .output, +body.theme-light pre { + background: #fffff0; + border-color: #1b1610; + color: #1b1610; + font-family: inherit; +} diff --git a/apps/demos-static/public/theme.js b/apps/demos-static/public/theme.js index 88dbd75..cddaaa4 100644 --- a/apps/demos-static/public/theme.js +++ b/apps/demos-static/public/theme.js @@ -1,32 +1,40 @@ -const demoThemeButtons = []; const demoThemeStorageKey = 'site-theme'; +const legacyDemoThemeStorageKey = 'cv-theme'; function normalizeDemoTheme(theme) { - return theme === 'light' ? 'light' : 'dark'; + return theme === 'light' || theme === 'fancy' ? 'light' : 'dark'; } function getStoredDemoTheme() { try { - return localStorage.getItem(demoThemeStorageKey); + return localStorage.getItem(demoThemeStorageKey) || localStorage.getItem(legacyDemoThemeStorageKey); } catch (_error) { return null; } } function storeDemoTheme(theme) { + const nextTheme = normalizeDemoTheme(theme); try { - localStorage.setItem(demoThemeStorageKey, theme); + localStorage.setItem(demoThemeStorageKey, nextTheme); + localStorage.removeItem(legacyDemoThemeStorageKey); } catch (_error) { } } +function getDemoThemeButtons() { + return [...document.querySelectorAll('[data-site-theme]')]; +} + function setDemoTheme(theme) { const nextTheme = normalizeDemoTheme(theme); + document.documentElement.classList.toggle('theme-light', nextTheme === 'light'); + document.documentElement.classList.toggle('theme-dark', nextTheme === 'dark'); document.body.classList.toggle('theme-light', nextTheme === 'light'); document.body.classList.toggle('theme-dark', nextTheme === 'dark'); - demoThemeButtons.forEach((button) => { - const active = button.dataset.siteTheme === nextTheme; + getDemoThemeButtons().forEach((button) => { + const active = normalizeDemoTheme(button.dataset.siteTheme) === nextTheme; button.classList.toggle('is-active', active); button.setAttribute('aria-pressed', active ? 'true' : 'false'); }); @@ -43,12 +51,13 @@ function installDemoThemeToolbar() { toolbar.setAttribute('aria-label', 'Theme'); toolbar.innerHTML = 'Theme'; nav.appendChild(toolbar); - - demoThemeButtons.push(...toolbar.querySelectorAll('[data-site-theme]')); - demoThemeButtons.forEach((button) => { - button.addEventListener('click', () => setDemoTheme(button.dataset.siteTheme)); - }); } +document.addEventListener('click', (event) => { + const button = event.target.closest('[data-site-theme]'); + if (!button) return; + setDemoTheme(button.dataset.siteTheme); +}); + installDemoThemeToolbar(); setDemoTheme(getStoredDemoTheme() || 'dark'); diff --git a/apps/website/blog.php b/apps/website/blog.php index a701f31..b7d67f0 100644 --- a/apps/website/blog.php +++ b/apps/website/blog.php @@ -890,7 +890,7 @@ function renderStackSourceLinks(string $stackKey, array $sourceLinks, string $so diff --git a/apps/website/cv-theme.js b/apps/website/cv-theme.js index 13a0c30..404a9ec 100644 --- a/apps/website/cv-theme.js +++ b/apps/website/cv-theme.js @@ -1,4 +1,3 @@ -const siteThemeButtons = [...document.querySelectorAll('[data-site-theme]')]; const cvPortrait = document.getElementById('cv-portrait-orbit'); const siteThemeStorageKey = 'site-theme'; const legacyCvThemeStorageKey = 'cv-theme'; @@ -16,20 +15,27 @@ function getStoredSiteTheme() { } function storeSiteTheme(theme) { + const nextTheme = normalizeSiteTheme(theme); try { - localStorage.setItem(siteThemeStorageKey, theme); + localStorage.setItem(siteThemeStorageKey, nextTheme); localStorage.removeItem(legacyCvThemeStorageKey); } catch (_error) { } } +function getSiteThemeButtons() { + return [...document.querySelectorAll('[data-site-theme]')]; +} + function setSiteTheme(theme) { const nextTheme = normalizeSiteTheme(theme); + document.documentElement.classList.toggle('theme-light', nextTheme === 'light'); + document.documentElement.classList.toggle('theme-dark', nextTheme === 'dark'); document.body.classList.toggle('theme-light', nextTheme === 'light'); document.body.classList.toggle('theme-dark', nextTheme === 'dark'); - siteThemeButtons.forEach((button) => { - const active = button.dataset.siteTheme === nextTheme; + getSiteThemeButtons().forEach((button) => { + const active = normalizeSiteTheme(button.dataset.siteTheme) === nextTheme; button.classList.toggle('is-active', active); button.setAttribute('aria-pressed', active ? 'true' : 'false'); }); @@ -37,8 +43,10 @@ function setSiteTheme(theme) { storeSiteTheme(nextTheme); } -siteThemeButtons.forEach((button) => { - button.addEventListener('click', () => setSiteTheme(button.dataset.siteTheme)); +document.addEventListener('click', (event) => { + const button = event.target.closest('[data-site-theme]'); + if (!button) return; + setSiteTheme(button.dataset.siteTheme); }); document.addEventListener('pointermove', (event) => { diff --git a/apps/website/cv.php b/apps/website/cv.php index 7a7e15e..d71b48e 100644 --- a/apps/website/cv.php +++ b/apps/website/cv.php @@ -259,7 +259,7 @@ $recruiterKeys = [ diff --git a/apps/website/index.php b/apps/website/index.php index 86ba17e..c68b781 100644 --- a/apps/website/index.php +++ b/apps/website/index.php @@ -155,7 +155,7 @@ $homeProofCards = [ diff --git a/apps/website/partials/translation_ui.php b/apps/website/partials/translation_ui.php index 6bad0f1..37ddeb8 100644 --- a/apps/website/partials/translation_ui.php +++ b/apps/website/partials/translation_ui.php @@ -44,6 +44,6 @@ const SAVE_URL = '/save_lang.php'; const CURRENT_LANG = ''; const STATIC_LANGS = ; - if (typeof OTHER_PAGES === 'undefined') { var OTHER_PAGES = []; } + window.OTHER_PAGES = Array.isArray(window.OTHER_PAGES) ? window.OTHER_PAGES : []; diff --git a/apps/website/styles.css b/apps/website/styles.css index d8ab0bf..ba9fe2f 100644 --- a/apps/website/styles.css +++ b/apps/website/styles.css @@ -2019,3 +2019,235 @@ body.theme-light .source-links a { font-size: 2.35rem; } } + +body.theme-dark { + background: #000; + color: #39ff14; + font-family: "Courier New", "Lucida Console", Monaco, monospace; + font-size: 1rem; + line-height: 1.56; +} + +body.theme-light { + background: #fffff0; + color: #1b1610; + font-family: "Brush Script MT", "Segoe Script", "Snell Roundhand", "Apple Chancery", cursive; + font-size: 1.12rem; + line-height: 1.68; +} + +body.theme-dark .top-nav, +body.theme-dark .site-theme-toolbar, +body.theme-dark .nav-left, +body.theme-dark .nav-right a, +body.theme-dark a, +body.theme-dark .blog-kicker, +body.theme-dark .section-kicker, +body.theme-dark .demo-label, +body.theme-dark h1, +body.theme-dark h2, +body.theme-dark h3, +body.theme-dark h4, +body.theme-dark strong { + color: #7cff7c; + font-family: inherit; +} + +body.theme-dark p, +body.theme-dark li, +body.theme-dark label, +body.theme-dark span, +body.theme-dark .blog-subtitle, +body.theme-dark .hero-role, +body.theme-dark .bio-intro, +body.theme-dark .bio-story, +body.theme-dark .cta, +body.theme-dark .diagram-caption, +body.theme-dark .source-links span, +body.theme-dark .visitor-idea-card footer { + color: #39ff14; +} + +body.theme-dark .container, +body.theme-dark.home-page .hero, +body.theme-dark .blog-hero, +body.theme-dark .demos-hero, +body.theme-dark .architecture-section, +body.theme-dark .case-studies, +body.theme-dark .activity-log, +body.theme-dark .homelab-todo, +body.theme-dark .tech-notes, +body.theme-dark .home-proof-card, +body.theme-dark .case-card, +body.theme-dark .demo-card, +body.theme-dark .message, +body.theme-dark .todo-list li, +body.theme-dark .activity-list li, +body.theme-dark .visitor-idea-card, +body.theme-dark .idea-status, +body.theme-dark .source-links a, +body.theme-dark .cv-impact-grid p, +body.theme-dark .cv-skill-grid article, +body.theme-dark .cv-recruiter-panel, +body.theme-dark .cv-proof-section, +body.theme-dark .cv-skill-section { + background: #000; + border-color: #1fbf3a; + color: #39ff14; + box-shadow: 0 0 16px rgba(57, 255, 20, 0.16); +} + +body.theme-dark .hero-actions a, +body.theme-dark .cv-recruiter-actions a, +body.theme-dark .case-card a, +body.theme-dark .idea-form button, +body.theme-dark .site-theme-option { + background: #000; + border-color: #39ff14; + color: #39ff14; + font-family: inherit; +} + +body.theme-dark .site-theme-option.is-active, +body.theme-dark .hero-actions a:hover, +body.theme-dark .cv-recruiter-actions a:hover, +body.theme-dark .case-card a:hover, +body.theme-dark .idea-form button:hover { + background: #062b06; + color: #b6ffb6; +} + +body.theme-dark .idea-form input, +body.theme-dark .idea-form textarea, +body.theme-dark .diagram-shell { + background: #000; + border-color: #1fbf3a; + color: #39ff14; + font-family: inherit; +} + +body.theme-dark .diagram-zone, +body.theme-dark .diagram-node rect { + fill: #000; + stroke: #1fbf3a; +} + +body.theme-dark .diagram-zone-title, +body.theme-dark .diagram-node text, +body.theme-dark .diagram-link-label, +body.theme-dark .diagram-node .diagram-small, +body.theme-dark .diagram-small { + fill: #39ff14; +} + +body.theme-dark .diagram-link { + stroke: #39ff14; +} + +body.theme-light .top-nav, +body.theme-light .site-theme-toolbar, +body.theme-light .nav-left, +body.theme-light .nav-right a, +body.theme-light a, +body.theme-light .blog-kicker, +body.theme-light .section-kicker, +body.theme-light .demo-label, +body.theme-light h1, +body.theme-light h2, +body.theme-light h3, +body.theme-light h4, +body.theme-light strong { + color: #1b1610; + font-family: inherit; +} + +body.theme-light p, +body.theme-light li, +body.theme-light label, +body.theme-light span, +body.theme-light .blog-subtitle, +body.theme-light .hero-role, +body.theme-light .bio-intro, +body.theme-light .bio-story, +body.theme-light .cta, +body.theme-light .diagram-caption, +body.theme-light .source-links span, +body.theme-light .visitor-idea-card footer { + color: #1b1610; +} + +body.theme-light .container, +body.theme-light.home-page .hero, +body.theme-light .blog-hero, +body.theme-light .demos-hero, +body.theme-light .architecture-section, +body.theme-light .case-studies, +body.theme-light .activity-log, +body.theme-light .homelab-todo, +body.theme-light .tech-notes, +body.theme-light .home-proof-card, +body.theme-light .case-card, +body.theme-light .demo-card, +body.theme-light .message, +body.theme-light .todo-list li, +body.theme-light .activity-list li, +body.theme-light .visitor-idea-card, +body.theme-light .idea-status, +body.theme-light .source-links a, +body.theme-light .cv-impact-grid p, +body.theme-light .cv-skill-grid article, +body.theme-light .cv-recruiter-panel, +body.theme-light .cv-proof-section, +body.theme-light .cv-skill-section { + background: #fffff0; + border-color: #1b1610; + color: #1b1610; + box-shadow: none; +} + +body.theme-light .hero-actions a, +body.theme-light .cv-recruiter-actions a, +body.theme-light .case-card a, +body.theme-light .idea-form button, +body.theme-light .site-theme-option { + background: #fffff0; + border-color: #1b1610; + color: #1b1610; + font-family: inherit; +} + +body.theme-light .site-theme-option.is-active, +body.theme-light .hero-actions a:hover, +body.theme-light .cv-recruiter-actions a:hover, +body.theme-light .case-card a:hover, +body.theme-light .idea-form button:hover { + background: #1b1610; + color: #fffff0; +} + +body.theme-light .idea-form input, +body.theme-light .idea-form textarea, +body.theme-light .diagram-shell { + background: #fffff0; + border-color: #1b1610; + color: #1b1610; + font-family: inherit; +} + +body.theme-light .diagram-zone, +body.theme-light .diagram-node rect { + fill: #fffff0; + stroke: #1b1610; +} + +body.theme-light .diagram-zone-title, +body.theme-light .diagram-node text, +body.theme-light .diagram-link-label, +body.theme-light .diagram-node .diagram-small, +body.theme-light .diagram-small { + fill: #1b1610; +} + +body.theme-light .diagram-link { + stroke: #1b1610; +}