From 66802e23d77a23b72ac786d049a6ce653c5150eb Mon Sep 17 00:00:00 2001 From: Tyler Hoang Date: Tue, 26 May 2026 19:28:43 -0700 Subject: redesign: add Y2K chrome theme + theme switcher MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Y2K Chrome / Frutiger Aero two-theme switcher (floating pill, top-right) - Theme persists via localStorage under 'tyler.theme', no flash on load - Chrome theme: brushed-metal panels, iridescent titlebar seam, holographic cursor, blueprint wallpaper, Audiowide/Michroma/Space Grotesk fonts - Aero theme: upgraded to Plus Jakarta Sans + IBM Plex Mono - Z-index hygiene: .icons → 10, .win → 50, .bubble-field → 0 - Sparkle cursor is theme-aware (cyan→pink for chrome, warm rainbow for aero) - Music toggle is theme-aware: bazaar theme (aero) / coolman (chrome), swaps live if you change theme while music is playing - Add img/wallpaper-chrome.png (blueprint wallpaper for chrome theme) Co-Authored-By: Claude Sonnet 4.6 --- aero.js | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 4 deletions(-) (limited to 'aero.js') diff --git a/aero.js b/aero.js index 98cb8ec..9429ccf 100644 --- a/aero.js +++ b/aero.js @@ -1,4 +1,4 @@ -// Shared Aero JS: bubbles, sparkle cursor, music toggle, drag windows, helpers. +// Shared Aero JS: bubbles, sparkle cursor, music toggle, drag windows, theme switcher, helpers. function spawnBubbles(host, count = 22) { const f = document.createElement('div'); @@ -50,8 +50,14 @@ function sparkleCursor() { s.className = 'sparkle'; s.style.left = e.clientX + 'px'; s.style.top = e.clientY + 'px'; - const hue = 30 + Math.random() * 200; - s.style.background = `radial-gradient(circle, oklch(95% 0.12 ${hue}) 0%, oklch(85% 0.18 ${hue} / 0.6) 40%, transparent 70%)`; + const theme = document.body.dataset.theme; + // chrome: iridescent / holographic palette (cyan→magenta→pink) + // aero: warm-cool rainbow as before + const hue = theme === 'chrome' + ? 200 + Math.random() * 160 + : 30 + Math.random() * 200; + const chroma = theme === 'chrome' ? 0.22 : 0.18; + s.style.background = `radial-gradient(circle, oklch(96% 0.10 ${hue}) 0%, oklch(82% ${chroma} ${hue} / 0.6) 40%, transparent 70%)`; document.body.appendChild(s); setTimeout(() => s.remove(), 900); }); @@ -147,6 +153,45 @@ function bindMusicToggle(root) { }); } +// THEME SWITCHER — Aero (Frutiger) ↔ Chrome (Y2K) +const THEME_KEY = 'tyler.theme'; +const THEMES = ['aero', 'chrome']; + +function getTheme() { + const t = localStorage.getItem(THEME_KEY); + return THEMES.includes(t) ? t : 'aero'; +} +function setTheme(t) { + if (!THEMES.includes(t)) t = 'aero'; + document.body.setAttribute('data-theme', t); + localStorage.setItem(THEME_KEY, t); + document.querySelectorAll('.theme-switcher button').forEach(b => { + b.classList.toggle('active', b.dataset.theme === t); + }); + try { window.dispatchEvent(new CustomEvent('themechange', { detail: t })); } catch(_){} +} +function mountThemeSwitcher(host) { + host = host || document.body; + const wrap = document.createElement('div'); + wrap.className = 'theme-switcher no-drag'; + wrap.innerHTML = THEMES.map(t => ` + + `).join(''); + host.appendChild(wrap); + wrap.querySelectorAll('button').forEach(b => { + b.addEventListener('click', () => setTheme(b.dataset.theme)); + }); + setTheme(getTheme()); + return wrap; +} +function initTheme() { + document.body.setAttribute('data-theme', getTheme()); +} + +// REAL API INTEGRATIONS + async function fetchLastFm(user = 'trollshotlol', key = 'e4d5c973811037717f7603f616259cdf', limit = 4) { const url = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${user}&api_key=${key}&format=json&limit=${limit}`; const r = await fetch(url); @@ -182,4 +227,11 @@ async function fetchReelMouthFeed(limit = 6) { return await r.json(); } -window.Aero = { spawnBubbles, makeClouds, sparkleCursor, makeDraggable, counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle, fetchLastFm, fetchFilms, fetchVisitorCount, fetchReelMouthFeed }; +window.Aero = { + spawnBubbles, makeClouds, sparkleCursor, makeDraggable, + counterHTML, nowPlayingHTML, animateEq, musicToggleHTML, bindMusicToggle, + // theme api + getTheme, setTheme, mountThemeSwitcher, initTheme, THEMES, + // real api integrations + fetchLastFm, fetchFilms, fetchVisitorCount, fetchReelMouthFeed, +}; -- cgit v1.3-2-g0d8e