From 3f6ba52014fd7044a03b4384b2c02591954ae87d Mon Sep 17 00:00:00 2001 From: mayil Date: Sat, 18 Oct 2025 16:21:35 +0530 Subject: [PATCH] theme_toggle_in_all_pages --- projects/animated-clock/index.html | 84 ++++--- projects/animated-clock/main.js | 104 +++++---- projects/animated-clock/styles.css | 207 +++++++++++++----- projects/bmi/index.html | 17 ++ projects/bmi/main.js | 16 ++ projects/bmi/styles.css | 92 +++++++- projects/currency/index.html | 17 ++ projects/currency/main.js | 18 ++ projects/currency/styles.css | 90 +++++++- projects/expense-tracker/index.html | 17 ++ projects/expense-tracker/main.js | 19 +- projects/expense-tracker/styles.css | 87 ++++++++ projects/image-slider/index.html | 17 ++ projects/image-slider/main.js | 16 ++ projects/image-slider/styles.css | 90 +++++++- projects/markdown/index.html | 34 +-- projects/markdown/main.js | 46 ++-- projects/markdown/styles.css | 155 +++++++------ projects/maze/index.html | 16 ++ projects/maze/main.js | 16 ++ projects/maze/styles.css | 90 +++++++- projects/memory-match/index.html | 17 ++ projects/memory-match/main.js | 20 ++ projects/memory-match/styles.css | 90 +++++++- projects/number-guessing-game/index.html | 17 ++ projects/number-guessing-game/main.js | 20 +- projects/number-guessing-game/styles.css | 90 +++++++- projects/pomodoro/index.html | 17 ++ projects/pomodoro/main.js | 18 ++ projects/pomodoro/styles.css | 91 +++++++- projects/qr-code-generator-scanner/index.html | 17 ++ projects/qr-code-generator-scanner/main.js | 19 +- projects/qr-code-generator-scanner/styles.css | 88 +++++++- projects/rock-paper-scissors/index.html | 17 ++ projects/rock-paper-scissors/main.js | 18 ++ projects/rock-paper-scissors/styles.css | 89 ++++++++ .../text-encryption-decryption/index.html | 17 ++ projects/text-encryption-decryption/main.js | 19 +- .../text-encryption-decryption/styles.css | 90 +++++++- projects/theme-switcher/index.html | 17 ++ projects/theme-switcher/main.js | 16 ++ projects/theme-switcher/styles.css | 90 +++++++- projects/todo/index.html | 17 ++ projects/todo/main.js | 16 ++ projects/todo/styles.css | 90 +++++++- projects/weather/index.html | 17 ++ projects/weather/main.js | 19 +- projects/weather/styles.css | 88 ++++++++ projects/whack-a-mole/index.html | 17 ++ projects/whack-a-mole/main.js | 18 ++ projects/whack-a-mole/styles.css | 91 ++++++++ 51 files changed, 2236 insertions(+), 262 deletions(-) diff --git a/projects/animated-clock/index.html b/projects/animated-clock/index.html index dc858cb..8ef6ba2 100644 --- a/projects/animated-clock/index.html +++ b/projects/animated-clock/index.html @@ -2,37 +2,61 @@ - - - Animated Clock - + + + Animated Clock + -
-

Animated Clock

-
- - -
- -

Smooth animation with requestAnimationFrame. Select a time zone to view different regional times.

-
- - + + + - \ No newline at end of file +
+

Animated Clock

+
+ + +
+ +

Smooth animation with requestAnimationFrame. Select a time zone to view different regional times.

+
+ + + + diff --git a/projects/animated-clock/main.js b/projects/animated-clock/main.js index 175c95e..2a53a7c 100644 --- a/projects/animated-clock/main.js +++ b/projects/animated-clock/main.js @@ -1,3 +1,6 @@ +// ------------------------------ +// CLOCK FUNCTION +// ------------------------------ const c = document.getElementById('clock'); const ctx = c.getContext('2d'); const timezoneSelect = document.getElementById('timezone-select'); @@ -5,59 +8,74 @@ const timezoneSelect = document.getElementById('timezone-select'); let selectedTimezone = 'local'; timezoneSelect.addEventListener('change', (e) => { - selectedTimezone = e.target.value; + selectedTimezone = e.target.value; }); function getCurrentTime() { - const now = new Date(); - if (selectedTimezone === 'local') { - return now; - } - - try { - const timeInTimezone = new Date(now.toLocaleString("en-US", {timeZone: selectedTimezone})); - const localTime = new Date(now.toLocaleString("en-US")); - const diff = localTime.getTime() - timeInTimezone.getTime(); - return new Date(now.getTime() - diff); - } catch (error) { - return now; - } + const now = new Date(); + if (selectedTimezone === 'local') return now; + + try { + const timeInTimezone = new Date(now.toLocaleString("en-US", { timeZone: selectedTimezone })); + const localTime = new Date(now.toLocaleString("en-US")); + const diff = localTime.getTime() - timeInTimezone.getTime(); + return new Date(now.getTime() - diff); + } catch (error) { + return now; + } } function draw() { - const now = getCurrentTime(); - const w = c.width, h = c.height, r = w / 2; - - ctx.clearRect(0, 0, w, h); - ctx.translate(r, r); - ctx.strokeStyle = '#93c5fd'; + const now = getCurrentTime(); + const w = c.width, h = c.height, r = w / 2; + + ctx.clearRect(0, 0, w, h); + ctx.translate(r, r); + ctx.strokeStyle = '#93c5fd'; + ctx.beginPath(); + ctx.arc(0, 0, r - 6, 0, Math.PI * 2); + ctx.stroke(); + + function hand(angle, len, width) { + ctx.save(); + ctx.rotate(angle); ctx.beginPath(); - ctx.arc(0, 0, r - 6, 0, Math.PI * 2); + ctx.lineWidth = width; + ctx.moveTo(0, 0); + ctx.lineTo(0, -len); ctx.stroke(); - - function hand(angle, len, width) { - ctx.save(); - ctx.rotate(angle); - ctx.beginPath(); - ctx.lineWidth = width; - ctx.moveTo(0, 0); - ctx.lineTo(0, -len); - ctx.stroke(); - ctx.restore(); - } - - const sec = now.getSeconds() + now.getMilliseconds() / 1000; - const min = now.getMinutes() + sec / 60; - const hr = ((now.getHours() % 12) + min / 60); - - hand(hr * Math.PI / 6, r * 0.5, 4); - hand(min * Math.PI / 30, r * 0.75, 3); - hand(sec * Math.PI / 30, r * 0.85, 1); - - ctx.setTransform(1, 0, 0, 1, 0, 0); - requestAnimationFrame(draw); + ctx.restore(); + } + + const sec = now.getSeconds() + now.getMilliseconds() / 1000; + const min = now.getMinutes() + sec / 60; + const hr = ((now.getHours() % 12) + min / 60); + + hand(hr * Math.PI / 6, r * 0.5, 4); + hand(min * Math.PI / 30, r * 0.75, 3); + hand(sec * Math.PI / 30, r * 0.85, 1); + + ctx.setTransform(1, 0, 0, 1, 0, 0); + requestAnimationFrame(draw); } ctx.strokeStyle = '#6ee7b7'; ctx.lineCap = 'round'; draw(); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/animated-clock/styles.css b/projects/animated-clock/styles.css index 4247a9d..51f39d5 100644 --- a/projects/animated-clock/styles.css +++ b/projects/animated-clock/styles.css @@ -1,87 +1,176 @@ body { - font-family: system-ui; - background: #0f0f12; - color: #eef1f8; - margin: 0; - padding: 2rem; - display: grid; - place-items: center + font-family: system-ui; + background: #0f0f12; + color: #eef1f8; + margin: 0; + padding: 2rem; + display: grid; + place-items: center; + transition: background 0.3s, color 0.3s; } main { - max-width: 560px; - width: 100%; - text-align: center; + max-width: 560px; + width: 100%; + text-align: center; } canvas { - background: #17171c; - border: 1px solid #262631; - border-radius: .5rem + background: #17171c; + border: 1px solid #262631; + border-radius: .5rem; } .controls { - margin-bottom: 1.5rem; - display: flex; - align-items: center; - justify-content: center; - gap: 0.75rem; - flex-wrap: wrap; + margin-bottom: 1.5rem; + display: flex; + align-items: center; + justify-content: center; + gap: 0.75rem; + flex-wrap: wrap; } .controls label { - font-weight: 500; - color: #eef1f8; + font-weight: 500; + color: #eef1f8; } .controls select { - background: #17171c; - border: 1px solid #262631; - border-radius: 0.375rem; - color: #eef1f8; - padding: 0.5rem 0.75rem; - font-size: 0.9rem; - min-width: 140px; - cursor: pointer; - transition: border-color 0.2s ease; + background: #17171c; + border: 1px solid #262631; + border-radius: 0.375rem; + color: #eef1f8; + padding: 0.5rem 0.75rem; + font-size: 0.9rem; + min-width: 140px; + cursor: pointer; + transition: border-color 0.2s ease; } .controls select:hover { - border-color: #93c5fd; + border-color: #93c5fd; } .controls select:focus { - outline: none; - border-color: #6ee7b7; - box-shadow: 0 0 0 2px rgba(110, 231, 183, 0.2); + outline: none; + border-color: #6ee7b7; + box-shadow: 0 0 0 2px rgba(110, 231, 183, 0.2); } .notes { - color: #a6adbb; - font-size: .9rem; - margin-top: 1rem; + color: #a6adbb; + font-size: .9rem; + margin-top: 1rem; } @media (max-width: 480px) { - body { - padding: 1rem; - } - - .controls { - flex-direction: column; - gap: 0.5rem; - margin-bottom: 1rem; - } - - .controls select { - min-width: 200px; - width: 100%; - max-width: 280px; - } - - canvas { - width: 100%; - max-width: 240px; - height: auto; - } -} \ No newline at end of file + body { + padding: 1rem; + } + + .controls { + flex-direction: column; + gap: 0.5rem; + margin-bottom: 1rem; + } + + .controls select { + min-width: 200px; + width: 100%; + max-width: 280px; + } + + canvas { + width: 100%; + max-width: 240px; + height: auto; + } +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/bmi/index.html b/projects/bmi/index.html index 5bf1cc1..d5ecc82 100644 --- a/projects/bmi/index.html +++ b/projects/bmi/index.html @@ -10,6 +10,23 @@ + +
diff --git a/projects/bmi/main.js b/projects/bmi/main.js index 031788d..9115213 100644 --- a/projects/bmi/main.js +++ b/projects/bmi/main.js @@ -577,3 +577,19 @@ document.addEventListener('DOMContentLoaded', () => { new BMICalculator(); }); +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/bmi/styles.css b/projects/bmi/styles.css index b8cc350..6e018d2 100644 --- a/projects/bmi/styles.css +++ b/projects/bmi/styles.css @@ -286,6 +286,8 @@ body { text-align: center; } + + .bmi-display { padding: 16px 20px; padding-top: 8px; @@ -660,4 +662,92 @@ body { white-space: normal; padding: 0 5px; } -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/currency/index.html b/projects/currency/index.html index ce2e70d..0e73078 100644 --- a/projects/currency/index.html +++ b/projects/currency/index.html @@ -9,6 +9,23 @@ + +

Currency Converter (Offline)

diff --git a/projects/currency/main.js b/projects/currency/main.js index a332c7d..d2ed1ef 100644 --- a/projects/currency/main.js +++ b/projects/currency/main.js @@ -183,3 +183,21 @@ swapBtn.addEventListener('keydown', (e) => { swapCurrencies(); } }); + + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/currency/styles.css b/projects/currency/styles.css index ec75515..4350ebe 100644 --- a/projects/currency/styles.css +++ b/projects/currency/styles.css @@ -223,4 +223,92 @@ button#swap { @media (max-width: 520px) { .row.inline { flex-direction: column; align-items: stretch; } .rate-row { flex-direction: column; align-items: stretch; } -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/expense-tracker/index.html b/projects/expense-tracker/index.html index 949a10b..df2fd99 100644 --- a/projects/expense-tracker/index.html +++ b/projects/expense-tracker/index.html @@ -9,6 +9,23 @@ + +

Expense Tracker

diff --git a/projects/expense-tracker/main.js b/projects/expense-tracker/main.js index 619ce8e..b62d2b4 100644 --- a/projects/expense-tracker/main.js +++ b/projects/expense-tracker/main.js @@ -68,4 +68,21 @@ } exportBtn.addEventListener('click', exportCSV); - render(); \ No newline at end of file + render(); + + const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/expense-tracker/styles.css b/projects/expense-tracker/styles.css index 0ac6953..cd121e0 100644 --- a/projects/expense-tracker/styles.css +++ b/projects/expense-tracker/styles.css @@ -1,2 +1,89 @@ body{font-family:system-ui;background:#0f0f12;color:#eef1f8;margin:0;padding:2rem;display:grid;place-items:center}main{max-width:760px;width:100%}form{display:flex;gap:.5rem;flex-wrap:wrap}input,button{font:inherit}input{padding:.5rem .75rem;border-radius:.5rem;border:1px solid #262631;background:#17171c;color:#eef1f8}button{background:#6ee7b7;color:#0b1020;border:none;padding:.5rem .75rem;border-radius:.5rem;font-weight:600;cursor:pointer}ul{list-style:none;padding:0;margin:1rem 0}.notes{color:#a6adbb;font-size:.9rem} +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/image-slider/index.html b/projects/image-slider/index.html index 64396d7..6783d50 100644 --- a/projects/image-slider/index.html +++ b/projects/image-slider/index.html @@ -9,6 +9,23 @@ + +

Image Slider

Slide
diff --git a/projects/image-slider/main.js b/projects/image-slider/main.js index 57c5ceb..e40c50a 100644 --- a/projects/image-slider/main.js +++ b/projects/image-slider/main.js @@ -1,2 +1,18 @@ const images = ['https://picsum.photos/seed/1/400/240', 'https://picsum.photos/seed/2/400/240', 'https://picsum.photos/seed/3/400/240']; let i = 0; const img = document.getElementById('img'); function render() { img.src = images[i]; } render(); document.getElementById('prev').addEventListener('click', () => { i = (i - 1 + images.length) % images.length; render(); }); document.getElementById('next').addEventListener('click', () => { i = (i + 1) % images.length; render(); }); // TODOs: autoplay/pause; keyboard focus; swipe; captions; indicators +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/image-slider/styles.css b/projects/image-slider/styles.css index 35f026e..b21c333 100644 --- a/projects/image-slider/styles.css +++ b/projects/image-slider/styles.css @@ -39,4 +39,92 @@ button { .notes { color: #a6adbb; font-size: .9rem -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/markdown/index.html b/projects/markdown/index.html index 585336b..7eb67f9 100644 --- a/projects/markdown/index.html +++ b/projects/markdown/index.html @@ -9,6 +9,23 @@ + +

Markdown Editor

@@ -16,22 +33,7 @@

Markdown Editor

- +

Add full parser, export as HTML, and themes.

diff --git a/projects/markdown/main.js b/projects/markdown/main.js index 4fd8dab..19a14d4 100644 --- a/projects/markdown/main.js +++ b/projects/markdown/main.js @@ -1,21 +1,15 @@ const input = document.getElementById('input'); const preview = document.getElementById('preview'); -const themeToggle = document.getElementById('themeToggle'); const exportHtml = document.getElementById('exportHtml'); +const themeToggle = document.getElementById('themeToggle'); const body = document.body; -// Theme management (matching home page system) +// Apply saved theme const currentTheme = localStorage.getItem('theme') || 'light'; if (currentTheme === 'dark') { body.classList.add('dark-mode'); } -function toggleTheme() { - body.classList.toggle('dark-mode'); - const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; - localStorage.setItem('theme', theme); -} - // Markdown parsing function naive(md) { return md @@ -36,26 +30,16 @@ function exportAsHtml() { - - - Exported Markdown - + + +Exported Markdown + - ${preview.innerHTML} +${preview.innerHTML} `; @@ -72,9 +56,13 @@ function exportAsHtml() { // Event listeners input.addEventListener('input', render); -themeToggle.addEventListener('click', toggleTheme); exportHtml.addEventListener('click', exportAsHtml); -// Initialize -applyTheme(currentTheme); +themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); +}); + +// Initial render render(); diff --git a/projects/markdown/styles.css b/projects/markdown/styles.css index a761f84..a4bf7fe 100644 --- a/projects/markdown/styles.css +++ b/projects/markdown/styles.css @@ -11,28 +11,6 @@ --input-bg: #0e0e13; } -body:not(.dark-mode) { - --bg: #f8f9fa; - --card: #ffffff; - --text: #1a1a1a; - --muted: #6b7280; - --bg-gradient-start: #f0f4f8; - --bg-gradient-end: #e2e8f0; - --border: #e5e7eb; - --input-bg: #ffffff; -} - -body.dark-mode { - --bg: #0f0f12; - --card: #17171c; - --text: #eef1f8; - --muted: #a6adbb; - --bg-gradient-start: #0b0b0e; - --bg-gradient-end: #121217; - --border: #262631; - --input-bg: #0e0e13; -} - * { box-sizing: border-box; } @@ -105,9 +83,69 @@ main { transform: translateY(0); } + +textarea { + width: 100%; + background: var(--input-bg); + color: var(--text); + border: 1px solid var(--border); + border-radius: .5rem; + padding: .75rem; + font-family: inherit; + font-size: 1rem; + line-height: 1.5; + resize: vertical; + transition: background 0.3s ease, border-color 0.3s ease; +} + +textarea:focus { + outline: none; + border-color: var(--accent); + box-shadow: 0 0 0 2px rgba(110, 231, 183, 0.2); +} + +.preview { + background: var(--input-bg); + border: 1px solid var(--border); + border-radius: .5rem; + padding: .75rem; + min-height: 200px; + transition: background 0.3s ease, border-color 0.3s ease; + line-height: 1.6; +} + +.preview h2 { + color: var(--text); + margin: 0 0 0.5rem 0; +} + +.preview h3 { + color: var(--text); + margin: 0 0 0.5rem 0; +} + +.preview strong { + font-weight: bold; +} + +.preview em { + font-style: italic; +} + +.preview li { + margin: 0.25rem 0; +} + +.notes { + color: var(--muted); + font-size: .9rem; + text-align: center; + margin: 0; +} + .theme-toggle { background: var(--card); - border: 2px solid var(--border); + border: 2px solid var(--border, #262631); border-radius: 50%; width: 50px; height: 50px; @@ -154,62 +192,41 @@ body:not(.dark-mode) .theme-toggle .moon-icon { opacity: 0; transform: rotate(-90deg); } - -textarea { - width: 100%; - background: var(--input-bg); - color: var(--text); - border: 1px solid var(--border); - border-radius: .5rem; - padding: .75rem; - font-family: inherit; - font-size: 1rem; - line-height: 1.5; - resize: vertical; - transition: background 0.3s ease, border-color 0.3s ease; -} - -textarea:focus { - outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 2px rgba(110, 231, 183, 0.2); +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; } -.preview { - background: var(--input-bg); - border: 1px solid var(--border); - border-radius: .5rem; - padding: .75rem; - min-height: 200px; - transition: background 0.3s ease, border-color 0.3s ease; - line-height: 1.6; +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; } -.preview h2 { - color: var(--text); - margin: 0 0 0.5rem 0; +body.dark-mode .controls label { + color: #0f0f12; } -.preview h3 { - color: var(--text); - margin: 0 0 0.5rem 0; +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; } -.preview strong { - font-weight: bold; +body.dark-mode .notes { + color: #4b5563; } -.preview em { - font-style: italic; +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; } -.preview li { - margin: 0.25rem 0; +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); } - -.notes { - color: var(--muted); - font-size: .9rem; - text-align: center; - margin: 0; -} \ No newline at end of file diff --git a/projects/maze/index.html b/projects/maze/index.html index 75b35c2..891d665 100644 --- a/projects/maze/index.html +++ b/projects/maze/index.html @@ -9,6 +9,22 @@ +

Maze

Contribute: generator, solver, keyboard navigation.

diff --git a/projects/maze/main.js b/projects/maze/main.js index 8a1f5ad..ba32f26 100644 --- a/projects/maze/main.js +++ b/projects/maze/main.js @@ -2,3 +2,19 @@ const c = document.getElementById('maze'); const ctx = c.getContext('2d'); // TODO: implement maze generation and basic player movement ctx.fillStyle = '#17171c'; ctx.fillRect(0, 0, c.width, c.height); ctx.fillStyle = '#6ee7b7'; ctx.fillRect(8, 8, 24, 24); +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/maze/styles.css b/projects/maze/styles.css index a3ef54d..b52f95f 100644 --- a/projects/maze/styles.css +++ b/projects/maze/styles.css @@ -22,4 +22,92 @@ canvas { .notes { color: #a6adbb; font-size: .9rem -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/memory-match/index.html b/projects/memory-match/index.html index d32da39..4c57367 100644 --- a/projects/memory-match/index.html +++ b/projects/memory-match/index.html @@ -9,6 +9,23 @@ + +

Memory Match

diff --git a/projects/memory-match/main.js b/projects/memory-match/main.js index 1242018..827cfb9 100644 --- a/projects/memory-match/main.js +++ b/projects/memory-match/main.js @@ -5,6 +5,24 @@ const grid = document.getElementById('grid'); const timeEl = document.querySelector('.time'); const bestEl = document.querySelector('.best'); +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); + + const emojis = ['🍎', '🍌', '🍇', '🍓', '🍒', '🍍', '🍊', '🍉']; let deck = shuffle([...emojis, ...emojis]).map((v, i) => ({ id: i, v, flipped: false, matched: false })); let first = null, second = null, lock = false; @@ -107,3 +125,5 @@ function loadBestTime() { loadBestTime(); render(); + + diff --git a/projects/memory-match/styles.css b/projects/memory-match/styles.css index 235fc66..28d81b1 100644 --- a/projects/memory-match/styles.css +++ b/projects/memory-match/styles.css @@ -46,4 +46,92 @@ button.card.flipped { margin-bottom: 1rem; font-size: 1.1rem; color: #a6adbb; -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/number-guessing-game/index.html b/projects/number-guessing-game/index.html index 3dcd566..ba8aaee 100644 --- a/projects/number-guessing-game/index.html +++ b/projects/number-guessing-game/index.html @@ -8,6 +8,23 @@ + +

Number Guessing Game

I'm thinking of a number between 1 and 100. Can you guess it?

diff --git a/projects/number-guessing-game/main.js b/projects/number-guessing-game/main.js index 21865d6..c0342f8 100644 --- a/projects/number-guessing-game/main.js +++ b/projects/number-guessing-game/main.js @@ -89,4 +89,22 @@ function initNumberGuessingGame() { setFeedback('', ''); } -window.addEventListener('DOMContentLoaded', initNumberGuessingGame); \ No newline at end of file +window.addEventListener('DOMContentLoaded', initNumberGuessingGame); + + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/number-guessing-game/styles.css b/projects/number-guessing-game/styles.css index c45c7ef..138e7a7 100644 --- a/projects/number-guessing-game/styles.css +++ b/projects/number-guessing-game/styles.css @@ -65,4 +65,92 @@ button:disabled { background: #1f1f27; border-color: #2a2a33; color: var(--muted background: linear-gradient(135deg, var(--accent), var(--accent-2)); border-color: #1e3a8a; } -#restart-btn:hover { filter: brightness(1.05); } \ No newline at end of file +#restart-btn:hover { filter: brightness(1.05); } + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/pomodoro/index.html b/projects/pomodoro/index.html index 72d5c92..26b2e8f 100644 --- a/projects/pomodoro/index.html +++ b/projects/pomodoro/index.html @@ -9,6 +9,23 @@ + +

Pomodoro Timer

25:00
diff --git a/projects/pomodoro/main.js b/projects/pomodoro/main.js index 74e6260..e746943 100644 --- a/projects/pomodoro/main.js +++ b/projects/pomodoro/main.js @@ -6,3 +6,21 @@ document.getElementById('start').addEventListener('click', () => { if (running) document.getElementById('reset').addEventListener('click', () => { clearInterval(t); running = false; secs = 25 * 60; render(); }); render(); // TODOs: settings for work/break; notifications; sound; stats history + + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/pomodoro/styles.css b/projects/pomodoro/styles.css index a650036..1af1413 100644 --- a/projects/pomodoro/styles.css +++ b/projects/pomodoro/styles.css @@ -31,4 +31,93 @@ button { .notes { color: #a6adbb; font-size: .9rem -} \ No newline at end of file +} + + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/qr-code-generator-scanner/index.html b/projects/qr-code-generator-scanner/index.html index da91799..26d4760 100644 --- a/projects/qr-code-generator-scanner/index.html +++ b/projects/qr-code-generator-scanner/index.html @@ -7,6 +7,23 @@ + +

QR Code Generator & Scanner

diff --git a/projects/qr-code-generator-scanner/main.js b/projects/qr-code-generator-scanner/main.js index 5e1eae6..5aabcd6 100644 --- a/projects/qr-code-generator-scanner/main.js +++ b/projects/qr-code-generator-scanner/main.js @@ -11,4 +11,21 @@ function initQRCodeGeneratorScanner() { // TODO: Download QR code } -window.addEventListener('DOMContentLoaded', initQRCodeGeneratorScanner); \ No newline at end of file +window.addEventListener('DOMContentLoaded', initQRCodeGeneratorScanner); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/qr-code-generator-scanner/styles.css b/projects/qr-code-generator-scanner/styles.css index 8cd3811..8cae5d1 100644 --- a/projects/qr-code-generator-scanner/styles.css +++ b/projects/qr-code-generator-scanner/styles.css @@ -1 +1,87 @@ -/* TODO: Style QR container, input, QR code display, download button, scan input, result display */ \ No newline at end of file +/* TODO: Style QR container, input, QR code display, download button, scan input, result display */.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/rock-paper-scissors/index.html b/projects/rock-paper-scissors/index.html index b13b199..b786efa 100644 --- a/projects/rock-paper-scissors/index.html +++ b/projects/rock-paper-scissors/index.html @@ -7,6 +7,23 @@ + +

Rock-Paper-Scissors Game

diff --git a/projects/rock-paper-scissors/main.js b/projects/rock-paper-scissors/main.js index b99abf1..8c3c720 100644 --- a/projects/rock-paper-scissors/main.js +++ b/projects/rock-paper-scissors/main.js @@ -73,3 +73,21 @@ function initRockPaperScissors() { } window.addEventListener("DOMContentLoaded", initRockPaperScissors); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); + diff --git a/projects/rock-paper-scissors/styles.css b/projects/rock-paper-scissors/styles.css index 1cf5b55..16a839f 100644 --- a/projects/rock-paper-scissors/styles.css +++ b/projects/rock-paper-scissors/styles.css @@ -107,3 +107,92 @@ h1 { gap: 0.5em; } } + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} + diff --git a/projects/text-encryption-decryption/index.html b/projects/text-encryption-decryption/index.html index 0bcf532..62ac956 100644 --- a/projects/text-encryption-decryption/index.html +++ b/projects/text-encryption-decryption/index.html @@ -7,6 +7,23 @@ + +

Text Encryption / Decryption Tool

diff --git a/projects/text-encryption-decryption/main.js b/projects/text-encryption-decryption/main.js index dbe0663..dbabca0 100644 --- a/projects/text-encryption-decryption/main.js +++ b/projects/text-encryption-decryption/main.js @@ -149,4 +149,21 @@ function initTextEncryptionDecryption() { updateCharCount(); } -window.addEventListener('DOMContentLoaded', initTextEncryptionDecryption); \ No newline at end of file +window.addEventListener('DOMContentLoaded', initTextEncryptionDecryption); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/text-encryption-decryption/styles.css b/projects/text-encryption-decryption/styles.css index 7743230..4828e1b 100644 --- a/projects/text-encryption-decryption/styles.css +++ b/projects/text-encryption-decryption/styles.css @@ -141,4 +141,92 @@ select, input[type="number"] { h1 { font-size: 1.4rem; } #tool-container { padding: 14px; } textarea { min-height: 100px; } -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/theme-switcher/index.html b/projects/theme-switcher/index.html index 7ffe68f..ee6d5f4 100644 --- a/projects/theme-switcher/index.html +++ b/projects/theme-switcher/index.html @@ -9,6 +9,23 @@ + +

Theme Switcher

diff --git a/projects/theme-switcher/main.js b/projects/theme-switcher/main.js index aa71c55..a628c9e 100644 --- a/projects/theme-switcher/main.js +++ b/projects/theme-switcher/main.js @@ -1,2 +1,18 @@ const input = document.getElementById('color'); document.getElementById('apply').addEventListener('click', () => { document.documentElement.style.setProperty('--accent', input.value); }); // TODOs: generate palettes (HSL); save themes (localStorage); share URL hash +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/theme-switcher/styles.css b/projects/theme-switcher/styles.css index d9059cd..3e3da3e 100644 --- a/projects/theme-switcher/styles.css +++ b/projects/theme-switcher/styles.css @@ -35,4 +35,92 @@ button { .notes { color: #a6adbb; font-size: .9rem -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/todo/index.html b/projects/todo/index.html index 7547331..6a37878 100644 --- a/projects/todo/index.html +++ b/projects/todo/index.html @@ -9,6 +9,23 @@ + +

Todo List

diff --git a/projects/todo/main.js b/projects/todo/main.js index a2b5a8c..6c445e9 100644 --- a/projects/todo/main.js +++ b/projects/todo/main.js @@ -48,3 +48,19 @@ function render() { render(); // TODOs: save to localStorage; add filter (all/active/done); sort; theme switcher +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/todo/styles.css b/projects/todo/styles.css index 50aea8d..3cbcc86 100644 --- a/projects/todo/styles.css +++ b/projects/todo/styles.css @@ -250,4 +250,92 @@ li.done label span { label { gap: 0.5rem; } -} \ No newline at end of file +} + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} diff --git a/projects/weather/index.html b/projects/weather/index.html index 257c757..2806557 100644 --- a/projects/weather/index.html +++ b/projects/weather/index.html @@ -9,6 +9,23 @@ + +

Weather

diff --git a/projects/weather/main.js b/projects/weather/main.js index a84627d..36113f4 100644 --- a/projects/weather/main.js +++ b/projects/weather/main.js @@ -182,4 +182,21 @@ unitBtn.addEventListener('click', () => { displayWeather(cache[cacheKey].data, currentCity); } } -}); \ No newline at end of file +}); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); diff --git a/projects/weather/styles.css b/projects/weather/styles.css index 5f618de..f9d945b 100644 --- a/projects/weather/styles.css +++ b/projects/weather/styles.css @@ -8,6 +8,94 @@ body { place-items: center; min-height: 100vh; } +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} + main { max-width: 560px; diff --git a/projects/whack-a-mole/index.html b/projects/whack-a-mole/index.html index 88b5488..18c1d91 100644 --- a/projects/whack-a-mole/index.html +++ b/projects/whack-a-mole/index.html @@ -7,6 +7,23 @@ + +

Whack-a-Mole

diff --git a/projects/whack-a-mole/main.js b/projects/whack-a-mole/main.js index 9133941..ef0fc74 100644 --- a/projects/whack-a-mole/main.js +++ b/projects/whack-a-mole/main.js @@ -83,3 +83,21 @@ document.addEventListener('keydown', (e) => { }); render(); + +const themeToggle = document.getElementById('themeToggle'); + const body = document.body; + + + const currentTheme = localStorage.getItem('theme') || 'light'; + if (currentTheme === 'dark') { + body.classList.add('dark-mode'); + } + + themeToggle.addEventListener('click', () => { + body.classList.toggle('dark-mode'); + + + const theme = body.classList.contains('dark-mode') ? 'dark' : 'light'; + localStorage.setItem('theme', theme); + }); + diff --git a/projects/whack-a-mole/styles.css b/projects/whack-a-mole/styles.css index e4b6108..de98ab9 100644 --- a/projects/whack-a-mole/styles.css +++ b/projects/whack-a-mole/styles.css @@ -8,6 +8,97 @@ body { place-items: center; } + +.theme-toggle { + background: var(--card); + border: 2px solid var(--border, #262631); + border-radius: 50%; + width: 50px; + height: 50px; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; + position: fixed; + top: 1rem; + right: 1rem; + z-index: 1000; + color: var(--text); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); +} + +.theme-toggle:hover { + transform: rotate(15deg) scale(1.1); + border-color: var(--accent); + box-shadow: 0 6px 16px rgba(110, 231, 183, 0.2); +} + +.theme-toggle svg { + position: absolute; + transition: all 0.3s ease; +} + +.theme-toggle .sun-icon { + opacity: 0; + transform: rotate(90deg); +} + +.theme-toggle .moon-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .sun-icon { + opacity: 1; + transform: rotate(0deg); +} + +body:not(.dark-mode) .theme-toggle .moon-icon { + opacity: 0; + transform: rotate(-90deg); +} +/* ------------------------------------ + DARK MODE THEME +------------------------------------ */ +body.dark-mode { + background: #eef1f8; + color: #0f0f12; +} + +body.dark-mode canvas { + background: #ffffff; + border-color: #cbd5e1; +} + +body.dark-mode .controls label { + color: #0f0f12; +} + +body.dark-mode .controls select { + background: #ffffff; + border: 1px solid #cbd5e1; + color: #0f0f12; +} + +body.dark-mode .notes { + color: #4b5563; +} + +/* Toggle button colors for dark mode */ +body.dark-mode .theme-toggle { + background: #e2e8f0; + border-color: #a1a1aa; + color: #0f0f12; +} + +body.dark-mode .theme-toggle:hover { + border-color: #2563eb; + box-shadow: 0 6px 16px rgba(37, 99, 235, 0.2); +} + + + main { max-width: 560px; width: 100%;