From 7e9bdfbd6c1f32f82317ff129f933d6bef15d422 Mon Sep 17 00:00:00 2001 From: Bianca Date: Wed, 9 Sep 2026 11:10:23 +0200 Subject: [PATCH 1/3] fix: hero --- src/components/ui/hero.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/ui/hero.tsx b/src/components/ui/hero.tsx index 18d0b47..efc7f9d 100644 --- a/src/components/ui/hero.tsx +++ b/src/components/ui/hero.tsx @@ -9,7 +9,7 @@ export function Hero({ }) { return (
-

+

{title}

Date: Wed, 9 Sep 2026 11:59:33 +0200 Subject: [PATCH 2/3] feat: add navigation easter egg component with animations and constants --- src/app/layout.tsx | 5 +- src/components/easter-egg/constants.ts | 29 +++++ .../easter-egg/navigation-easter-egg.tsx | 72 ++++++++++++ src/components/easter-egg/types.ts | 4 + src/components/ui/generic-card.tsx | 6 + src/styles/animations.css | 110 ++++++++++++++++++ 6 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 src/components/easter-egg/constants.ts create mode 100644 src/components/easter-egg/navigation-easter-egg.tsx create mode 100644 src/components/easter-egg/types.ts create mode 100644 src/components/ui/generic-card.tsx diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 40ca3b1..d5070fe 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,4 +1,5 @@ import { ConditionalFooter } from "@/components/conditional-footer" +import { NavigationEasterEgg } from "@/components/easter-egg/navigation-easter-egg" import { Header } from "@/components/header/header" import { Shape } from "@/components/shapes" import { ThemeProvider } from "@/components/theme-provider" @@ -79,11 +80,11 @@ export default function RootLayout({ children }: Readonly<{ children: React.Reac

-
+
{children} -
+ diff --git a/src/components/easter-egg/constants.ts b/src/components/easter-egg/constants.ts new file mode 100644 index 0000000..6863a6f --- /dev/null +++ b/src/components/easter-egg/constants.ts @@ -0,0 +1,29 @@ +import { matchesRoutePrefix } from "@/utils/route-match" +import type { EasterEggPhase, NavCategory, PhaseTransition } from "./types" + +const HOME_PATH = "/" +const GROUPS_PREFIX = "/groups" + +export const TRIGGER_COUNT = 10 + +// chiavi opzionali perché non tutte le fasi hanno una fase successiva (cioé idle) +export const PHASE_TRANSITIONS: Partial> = { + glitch: { to: "card", delay: 1200 }, + card: { to: "idle", delay: 10000 }, +} + +export const PUNCHLINES = [ + "Hai trovato l'easter egg.\nOra torna a studiare.", + "Avanti e indietro, avanti e indietro...\nTi senti realizzato?", + `COMPLIMENTI.\nHai sprecato ${TRIGGER_COUNT} click per questo.`, + "Non c'è nient'altro qui.\nPuoi tornare alla tua vita.", + "Il PoliNetwork ti osserva\nda quando hai iniziato a cliccare.", + "Bel tentativo.\nMa qui non succede nient'altro di strano.", + "Home, Groups, Home, Groups...\nHai capito il concetto di loop?", +] + +export function getCategory(pathname: string): NavCategory { + if (pathname === HOME_PATH) return "home" + if (matchesRoutePrefix(pathname, GROUPS_PREFIX)) return "groups" + return "other" +} diff --git a/src/components/easter-egg/navigation-easter-egg.tsx b/src/components/easter-egg/navigation-easter-egg.tsx new file mode 100644 index 0000000..7171256 --- /dev/null +++ b/src/components/easter-egg/navigation-easter-egg.tsx @@ -0,0 +1,72 @@ +"use client" + +import Image from "next/image" +import { usePathname } from "next/navigation" +import type { ReactNode } from "react" +import { useEffect, useRef, useState } from "react" +import { GenericCard } from "@/components/ui/generic-card" +import { cn } from "@/lib/utils" +import { getCategory, PHASE_TRANSITIONS, PUNCHLINES, TRIGGER_COUNT } from "./constants" +import type { EasterEggPhase, NavCategory } from "./types" + +export function NavigationEasterEgg({ children, className }: { children: ReactNode; className?: string }) { + const pathname = usePathname() + const lastCategoryRef = useRef(null) + const toggleCountRef = useRef(0) + const [phase, setPhase] = useState("idle") + const [punchline, setPunchline] = useState(PUNCHLINES[0]) + + useEffect(() => { + const category = getCategory(pathname) + const lastCategory = lastCategoryRef.current + + if (category === "other") { + toggleCountRef.current = 0 + lastCategoryRef.current = null + return + } + + if (lastCategory && lastCategory !== category) { + toggleCountRef.current += 1 + if (toggleCountRef.current >= TRIGGER_COUNT) { + toggleCountRef.current = 0 + setPunchline(PUNCHLINES[Math.floor(Math.random() * PUNCHLINES.length)]) + setPhase("glitch") + } + } + + lastCategoryRef.current = category + }, [pathname]) + + useEffect(() => { + const next = PHASE_TRANSITIONS[phase] + if (!next) return + const timeout = setTimeout(() => setPhase(next.to), next.delay) + return () => clearTimeout(timeout) + }, [phase]) + + return ( + <> +
{children}
+ + {phase === "glitch" && ( +