commit dcf9de20f96b597723bd08d0e7afa9a3d5d83ce9 from: Rohan Verma date: Wed Oct 28 22:30:34 2026 UTC replace the theme toggle with a light switch icon that clicks. commit - 190cf253c5f3813c4e281a8b152f6d8366fe368e commit + dcf9de20f96b597723bd08d0e7afa9a3d5d83ce9 blob - 390f89a32c2ca81867a88aec9dfa31c26642f142 blob + 2321a6c17d6a6db66a8803eda85f94d0ec0655f1 --- got/index.html +++ got/index.html @@ -4,8 +4,8 @@ Repositories - Rohan Verma - - + +
Rohan Verma @@ -14,7 +14,7 @@ work got résumé - +
blob - 64318ab3aa6e91d1de119142a93d5dc61dfbf2e8 blob + b4463471dd312827bf7194ce030782ef7421d7dc --- index.html +++ index.html @@ -5,8 +5,8 @@ - - + +
@@ -16,7 +16,7 @@ work got résumé - +
blob - 010f6cb04da28d660ab73484487e207c1bdc7d13 blob + 3bb481e4aae16ba0a928718de6911d14ea026b54 --- static/style.css +++ static/style.css @@ -126,6 +126,21 @@ nav a, .theme { .theme:hover { color: var(--accent); } +/* a light switch: on is light mode, off is dark mode + * (icons from svgrepo.com, 441672 and 441673). Drawn as a mask so it + * takes the text colour, and turns orange on hover like the links. */ +.theme .switch { + display: block; + width: 14px; + height: 23px; + background: currentColor; + -webkit-mask: url(/static/switch-on.svg) center / contain no-repeat; + mask: url(/static/switch-on.svg) center / contain no-repeat; +} +[data-theme="dark"] .theme .switch { + -webkit-mask-image: url(/static/switch-off.svg); + mask-image: url(/static/switch-off.svg); +} .theme:focus-visible { outline: 1px solid var(--accent); outline-offset: 2px; blob - b01728be798c5cd0c051f93dfed44ae003e4c92d blob + 0403e140c370526eeb32c8257669ab3e21deb55d --- static/theme.js +++ static/theme.js @@ -9,10 +9,36 @@ function label(button) { var dark = root.getAttribute("data-theme") === "dark"; - button.textContent = dark ? "light" : "dark"; button.setAttribute("aria-pressed", dark); + button.setAttribute("aria-label", dark + ? "Light switch: turn on for light mode" + : "Light switch: turn off for dark mode"); + button.title = dark ? "lights on" : "lights off"; } + /* a short switch click, synthesised so there is no sound file: + * a burst of noise that dies away in a few milliseconds, pitched + * a little higher for on than for off */ + var audio; + function click(on) { + try { + audio = audio || new (window.AudioContext || window.webkitAudioContext)(); + var t = audio.currentTime, n = Math.floor(audio.sampleRate * .03); + var buf = audio.createBuffer(1, n, audio.sampleRate), d = buf.getChannelData(0); + for (var i = 0; i < n; i++) + d[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / n, 8); + var src = audio.createBufferSource(), band = audio.createBiquadFilter(); + var gain = audio.createGain(); + src.buffer = buf; + band.type = "bandpass"; + band.frequency.value = on ? 3200 : 2400; + band.Q.value = 1.5; + gain.gain.value = .6; + src.connect(band).connect(gain).connect(audio.destination); + src.start(t); + } catch (e) {} + } + document.addEventListener("DOMContentLoaded", function () { var button = document.querySelector(".theme"); if (!button) @@ -28,6 +54,7 @@ localStorage.setItem("theme", dark ? "dark" : "light"); } catch (e) {} label(button); + click(!dark); }); }); })(); blob - /dev/null blob + ac7c8c12bfff2d545e12b3fabb48973149754af2 (mode 644) --- /dev/null +++ static/switch-off.svg @@ -0,0 +1 @@ + blob - /dev/null blob + 61d4cdc4d88c8f92453414ba2f8752cbfe62528a (mode 644) --- /dev/null +++ static/switch-on.svg @@ -0,0 +1 @@ + blob - 9593972ac8f607be007e81c7e8b1582587fe13d3 blob + e49ac35db0c73da8e9df9be037c654ee2f9b21a6 --- work/index.html +++ work/index.html @@ -4,8 +4,8 @@ Work - Rohan Verma - - + +
@@ -15,7 +15,7 @@ work got résumé - +