Rohan Verma

Commit Diff


commit - 190cf253c5f3813c4e281a8b152f6d8366fe368e
commit + dcf9de20f96b597723bd08d0e7afa9a3d5d83ce9
blob - 390f89a32c2ca81867a88aec9dfa31c26642f142
blob + 2321a6c17d6a6db66a8803eda85f94d0ec0655f1
--- got/index.html
+++ got/index.html
@@ -4,8 +4,8 @@
 <title>Repositories - Rohan Verma</title>
 <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="stylesheet" href="/static/style.css?v=10">
-<script src="/static/theme.js?v=1"></script>
+<link rel="stylesheet" href="/static/style.css?v=13">
+<script src="/static/theme.js?v=3"></script>
 <header class="topbar">
 	<div>
 		<a class="wordmark" href="/"><img class="signature" src="/static/signature.png" alt="" width="28" height="28">Rohan Verma</a>
@@ -14,7 +14,7 @@
 			<a href="/work">work</a>
 			<a href="/got">got</a>
 			<a href="/static/resume.pdf">résumé</a>
-			<button class="theme" type="button" aria-pressed="false">dark</button>
+			<button class="theme" type="button" aria-pressed="false" aria-label="Light switch: turn off for dark mode" title="lights off"><span class="switch"></span></button>
 		</nav>
 	</div>
 </header>
blob - 64318ab3aa6e91d1de119142a93d5dc61dfbf2e8
blob + b4463471dd312827bf7194ce030782ef7421d7dc
--- index.html
+++ index.html
@@ -5,8 +5,8 @@
 <meta name="description" content="Rohan Verma (18), Computer Science student at Northeastern University. Systems, self-hosting, and Minecraft mods with over 1M downloads.">
 <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="stylesheet" href="/static/style.css?v=10">
-<script src="/static/theme.js?v=1"></script>
+<link rel="stylesheet" href="/static/style.css?v=13">
+<script src="/static/theme.js?v=3"></script>
 
 <header class="topbar">
 	<div>
@@ -16,7 +16,7 @@
 			<a href="/work">work</a>
 			<a href="/got">got</a>
 			<a href="/static/resume.pdf">résumé</a>
-			<button class="theme" type="button" aria-pressed="false">dark</button>
+			<button class="theme" type="button" aria-pressed="false" aria-label="Light switch: turn off for dark mode" title="lights off"><span class="switch"></span></button>
 		</nav>
 	</div>
 </header>
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 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="51 61 54 89" width="14" height="23"><path fill-rule="evenodd" d="M103.226 79.0832C101.914 84.7082 98.575 108.956 98.575 108.956C98.575 108.956 98.788 127.791 98.575 139.835C98.483 144.981 96.846 147.725 91.597 147.725C82.764 147.725 68.137 148.515 59.593 148.515C54.185 148.515 52.619 143.981 52.616 138.258C52.614 135.291 53.048 63.3042 53.048 63.3042L91.597 62.5142C91.597 62.5142 96.199 66.1542 100.125 70.4042C102.315 72.7762 104.546 73.4222 103.226 79.0832ZM77.738 138.144C91.908 138.144 91.819 116.647 77.98 116.647C62.828 116.647 63.514 138.144 77.738 138.144ZM84.435 85.6212L77.419 85.1052L75.009 100.595H81.508L84.435 85.6212ZM89.304 68.3062L59 69.2872L58.804 107.733L60.164 107.877L62.876 76.9372L97.503 76.3062L89.304 68.3062ZM77.796 121.877C84.899 121.877 84.944 132.909 77.671 132.909C70.372 132.909 70.02 121.877 77.796 121.877Z"/></svg>
blob - /dev/null
blob + 61d4cdc4d88c8f92453414ba2f8752cbfe62528a (mode 644)
--- /dev/null
+++ static/switch-on.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="51 61 54 89" width="14" height="23"><path fill-rule="evenodd" d="M91.597 148.515L53.048 147.726C53.048 147.726 52.612 75.7392 52.615 72.7712C52.619 67.0482 54.185 62.5142 59.593 62.5142C68.136 62.5142 82.765 63.3042 91.597 63.3042C96.845 63.3042 98.484 66.0482 98.575 71.1942C98.789 83.2382 98.575 104.332 98.575 104.332C98.575 104.332 101.915 126.321 103.226 131.947C104.546 137.609 102.316 138.254 100.125 140.626C96.198 144.875 91.597 148.515 91.597 148.515ZM91.597 105.91L92.372 70.6172L59.81 69.8272L60.026 107.487L63.902 133.524L96.25 134.314L91.597 105.91ZM77.309 109.882C91.142 109.882 93.574 129.503 80.064 129.503C65.272 129.503 63.424 109.882 77.309 109.882ZM79.146 123.965C85.026 123.965 83.968 115.425 77.947 115.425C71.902 115.425 72.707 123.965 79.146 123.965ZM72.632 94.0552L72.373 77.0452L80.139 77.2162L79.9 94.2892L72.632 94.0552Z"/></svg>
blob - 9593972ac8f607be007e81c7e8b1582587fe13d3
blob + e49ac35db0c73da8e9df9be037c654ee2f9b21a6
--- work/index.html
+++ work/index.html
@@ -4,8 +4,8 @@
 <title>Work - Rohan Verma</title>
 <link rel="icon" type="image/x-icon" href="/static/favicon.ico">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<link rel="stylesheet" href="/static/style.css?v=10">
-<script src="/static/theme.js?v=1"></script>
+<link rel="stylesheet" href="/static/style.css?v=13">
+<script src="/static/theme.js?v=3"></script>
 
 <header class="topbar">
 	<div>
@@ -15,7 +15,7 @@
 			<a href="/work">work</a>
 			<a href="/got">got</a>
 			<a href="/static/resume.pdf">résumé</a>
-			<button class="theme" type="button" aria-pressed="false">dark</button>
+			<button class="theme" type="button" aria-pressed="false" aria-label="Light switch: turn off for dark mode" title="lights off"><span class="switch"></span></button>
 		</nav>
 	</div>
 </header>