Skip to content

Commit 98bbc51

Browse files
committed
Small Modification
1 parent ac453cf commit 98bbc51

2 files changed

Lines changed: 296 additions & 0 deletions

File tree

docs/website/app.js

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ const DocsState = {
5353

5454
const DocsElements = {
5555
body: document.body,
56+
topbarLogo: document.getElementById("topbar-logo"),
57+
topbarVersion: document.getElementById("topbar-version"),
5658
topbarSearch: document.getElementById("topbar-search"),
5759
sidebar: document.getElementById("sidebar"),
5860
sidebarTabs: document.getElementById("sidebar-tabs"),
@@ -63,6 +65,7 @@ const DocsElements = {
6365
searchResults: document.getElementById("docs-search-results"),
6466
homeHeroLogo: document.getElementById("home-hero-logo"),
6567
homeHeroEgg: document.getElementById("home-hero-egg"),
68+
siteFooter: document.getElementById("site-footer"),
6669
title: document.querySelector("title")
6770
};
6871

@@ -245,6 +248,204 @@ const Sidebar = (() => {
245248
return { render, syncActive, setOpen, toggle };
246249
})();
247250

251+
const EasterEgg = (() => {
252+
const toastId = "egg-toast";
253+
const secretQueries = new Set([
254+
"asrfrb",
255+
"reconparty",
256+
"upupdowndownleftrightleftrightba"
257+
]);
258+
259+
let logoTapCount = 0;
260+
let logoTapTimer = null;
261+
let footerTapCount = 0;
262+
let footerTapTimer = null;
263+
let longPressTimer = null;
264+
let overdriveTimer = null;
265+
let toastTimer = null;
266+
let lastSecretQuery = "";
267+
268+
function ensureToast() {
269+
let toast = document.getElementById(toastId);
270+
if (toast) {
271+
return toast;
272+
}
273+
274+
toast = document.createElement("div");
275+
toast.id = toastId;
276+
toast.className = "egg-toast";
277+
toast.setAttribute("aria-live", "polite");
278+
DocsElements.body.appendChild(toast);
279+
return toast;
280+
}
281+
282+
function showToast(message) {
283+
const toast = ensureToast();
284+
toast.textContent = message;
285+
toast.classList.add("show");
286+
287+
if (toastTimer) {
288+
window.clearTimeout(toastTimer);
289+
}
290+
291+
toastTimer = window.setTimeout(() => {
292+
toast.classList.remove("show");
293+
}, 2200);
294+
}
295+
296+
function spawnConfetti(count = 20) {
297+
const layer = document.createElement("div");
298+
layer.className = "egg-confetti-layer";
299+
DocsElements.body.appendChild(layer);
300+
301+
const colors = ["#ff5a5f", "#ffd166", "#7ee787", "#79c0ff", "#c297ff"];
302+
const total = Math.max(8, Math.min(count, 48));
303+
304+
for (let i = 0; i < total; i += 1) {
305+
const bit = document.createElement("span");
306+
bit.className = "egg-confetti";
307+
bit.style.left = `${Math.random() * 100}%`;
308+
bit.style.background = colors[i % colors.length];
309+
bit.style.setProperty("--egg-drift", `${(Math.random() * 180) - 90}px`);
310+
bit.style.animationDuration = `${2.2 + (Math.random() * 1.8)}s`;
311+
bit.style.animationDelay = `${Math.random() * 0.25}s`;
312+
layer.appendChild(bit);
313+
}
314+
315+
window.setTimeout(() => {
316+
layer.remove();
317+
}, 3200);
318+
}
319+
320+
function triggerOverdrive() {
321+
DocsElements.body.classList.add("egg-overdrive");
322+
showToast("Recon overdrive enabled for 12 seconds");
323+
spawnConfetti(24);
324+
325+
if (overdriveTimer) {
326+
window.clearTimeout(overdriveTimer);
327+
}
328+
overdriveTimer = window.setTimeout(() => {
329+
DocsElements.body.classList.remove("egg-overdrive");
330+
}, 12000);
331+
}
332+
333+
function toggleBlueprintMode() {
334+
const enabled = DocsElements.body.classList.toggle("egg-blueprint");
335+
showToast(enabled ? "Blueprint mode enabled" : "Blueprint mode disabled");
336+
}
337+
338+
function bindLogoTapCombo() {
339+
if (!DocsElements.topbarLogo) {
340+
return;
341+
}
342+
343+
DocsElements.topbarLogo.addEventListener("click", () => {
344+
logoTapCount += 1;
345+
if (logoTapTimer) {
346+
window.clearTimeout(logoTapTimer);
347+
}
348+
349+
logoTapTimer = window.setTimeout(() => {
350+
logoTapCount = 0;
351+
}, 1800);
352+
353+
if (logoTapCount >= 5) {
354+
logoTapCount = 0;
355+
triggerOverdrive();
356+
}
357+
});
358+
}
359+
360+
function bindVersionLongPress() {
361+
if (!DocsElements.topbarVersion) {
362+
return;
363+
}
364+
365+
const startPress = (event) => {
366+
if (event.type === "mousedown" && event.button !== 0) {
367+
return;
368+
}
369+
if (longPressTimer) {
370+
window.clearTimeout(longPressTimer);
371+
}
372+
longPressTimer = window.setTimeout(() => {
373+
toggleBlueprintMode();
374+
}, 800);
375+
};
376+
377+
const cancelPress = () => {
378+
if (longPressTimer) {
379+
window.clearTimeout(longPressTimer);
380+
longPressTimer = null;
381+
}
382+
};
383+
384+
DocsElements.topbarVersion.addEventListener("mousedown", startPress);
385+
DocsElements.topbarVersion.addEventListener("mouseup", cancelPress);
386+
DocsElements.topbarVersion.addEventListener("mouseleave", cancelPress);
387+
DocsElements.topbarVersion.addEventListener("touchstart", startPress, { passive: true });
388+
DocsElements.topbarVersion.addEventListener("touchend", cancelPress);
389+
DocsElements.topbarVersion.addEventListener("touchcancel", cancelPress);
390+
}
391+
392+
function bindFooterTapCombo() {
393+
if (!DocsElements.siteFooter) {
394+
return;
395+
}
396+
397+
DocsElements.siteFooter.addEventListener("click", (event) => {
398+
const target = event.target;
399+
if (!(target instanceof HTMLElement)) {
400+
return;
401+
}
402+
403+
const tapTarget = target.closest(".footer-col-title");
404+
if (!tapTarget) {
405+
return;
406+
}
407+
408+
footerTapCount += 1;
409+
if (footerTapTimer) {
410+
window.clearTimeout(footerTapTimer);
411+
}
412+
footerTapTimer = window.setTimeout(() => {
413+
footerTapCount = 0;
414+
}, 1600);
415+
416+
if (footerTapCount >= 3) {
417+
footerTapCount = 0;
418+
showToast("Hidden trace: keep calm, recon smart");
419+
spawnConfetti(16);
420+
}
421+
});
422+
}
423+
424+
function onSearchInput(value = "") {
425+
const normalized = value.toLowerCase().replace(/[^a-z0-9]/g, "");
426+
if (!secretQueries.has(normalized)) {
427+
lastSecretQuery = "";
428+
return;
429+
}
430+
431+
if (lastSecretQuery === normalized) {
432+
return;
433+
}
434+
435+
lastSecretQuery = normalized;
436+
showToast("Secret query accepted");
437+
spawnConfetti(28);
438+
}
439+
440+
function bind() {
441+
bindLogoTapCombo();
442+
bindVersionLongPress();
443+
bindFooterTapCombo();
444+
}
445+
446+
return { bind, onSearchInput };
447+
})();
448+
248449
const Search = (() => {
249450
function setOpen(open) {
250451
DocsState.searchOpen = open;
@@ -299,6 +500,7 @@ const Search = (() => {
299500

300501
function bind() {
301502
DocsElements.searchInput?.addEventListener("input", (event) => {
503+
EasterEgg.onSearchInput(event.target.value);
302504
setOpen(true);
303505
renderResults(event.target.value);
304506
});
@@ -506,6 +708,7 @@ const App = (() => {
506708
function init() {
507709
DocsHelpers.syncCurrentSection();
508710
Sidebar.render();
711+
EasterEgg.bind();
509712
Search.bind();
510713
Search.setOpen(false);
511714
bindHomeEasterEgg();

docs/website/styles.css

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,92 @@ body::before {
6060
pointer-events: none; z-index: 9999;
6161
}
6262

63+
body.egg-blueprint {
64+
--r0: #7bdcff;
65+
--r1: #4ec4eb;
66+
--r2: #1b92c2;
67+
--r3: #0f4f6d;
68+
--border: rgba(123, 220, 255, 0.28);
69+
--border2: rgba(123, 220, 255, 0.14);
70+
--glow: rgba(123, 220, 255, 0.26);
71+
--glowf: rgba(123, 220, 255, 0.10);
72+
}
73+
74+
body.egg-overdrive #topbar-logo,
75+
body.egg-overdrive .home-hero-logo {
76+
animation-duration: 1.1s;
77+
}
78+
79+
body.egg-overdrive::after {
80+
content: '';
81+
position: fixed;
82+
inset: 0;
83+
pointer-events: none;
84+
z-index: 9980;
85+
background: radial-gradient(circle at 20% 10%, rgba(255, 26, 26, 0.18), transparent 30%),
86+
radial-gradient(circle at 80% 90%, rgba(255, 100, 100, 0.16), transparent 34%);
87+
animation: egg-pulse-overlay 1.2s ease-in-out infinite;
88+
}
89+
90+
@keyframes egg-pulse-overlay {
91+
0%, 100% { opacity: 0.22; }
92+
50% { opacity: 0.42; }
93+
}
94+
95+
.egg-toast {
96+
position: fixed;
97+
right: 16px;
98+
bottom: 16px;
99+
z-index: 12000;
100+
max-width: min(88vw, 420px);
101+
padding: 10px 14px;
102+
border-radius: 10px;
103+
border: 1px solid var(--border);
104+
background: rgba(12, 16, 22, 0.95);
105+
color: var(--terminal-text);
106+
font-family: var(--mono);
107+
font-size: 0.72rem;
108+
letter-spacing: 0.03em;
109+
box-shadow: 0 12px 34px rgba(0, 0, 0, 0.35);
110+
opacity: 0;
111+
transform: translateY(10px);
112+
transition: opacity 0.2s ease, transform 0.2s ease;
113+
pointer-events: none;
114+
}
115+
116+
.egg-toast.show {
117+
opacity: 1;
118+
transform: translateY(0);
119+
}
120+
121+
.egg-confetti-layer {
122+
position: fixed;
123+
inset: 0;
124+
pointer-events: none;
125+
z-index: 11950;
126+
overflow: hidden;
127+
}
128+
129+
.egg-confetti {
130+
position: absolute;
131+
top: -10vh;
132+
width: 8px;
133+
height: 14px;
134+
border-radius: 2px;
135+
opacity: 0.95;
136+
animation-name: egg-confetti-fall;
137+
animation-timing-function: linear;
138+
animation-fill-mode: forwards;
139+
transform: translate3d(0, 0, 0) rotate(0deg);
140+
}
141+
142+
@keyframes egg-confetti-fall {
143+
to {
144+
transform: translate3d(var(--egg-drift, 0px), 115vh, 0) rotate(760deg);
145+
opacity: 0;
146+
}
147+
}
148+
63149
a { color: var(--r0); text-decoration: none; }
64150
a:hover { text-decoration: underline; }
65151
strong { color: var(--r0); font-weight: 700; }
@@ -1456,4 +1542,11 @@ tbody td code { white-space: nowrap; }
14561542
.stat-strip { grid-template-columns: 1fr; }
14571543
.install-grid { grid-template-columns: 1fr; }
14581544
#site-footer { grid-template-columns: 1fr; }
1545+
1546+
.egg-toast {
1547+
right: 10px;
1548+
bottom: 10px;
1549+
max-width: calc(100vw - 20px);
1550+
font-size: 0.68rem;
1551+
}
14591552
}

0 commit comments

Comments
 (0)