From b88f2de8656f8f7bec33c9bf81e58862f48e761b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Sun, 10 May 2026 10:25:28 +0200 Subject: [PATCH] feat(dashboard): recent-achievements card celebrates hidden unlocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the unlock notifier sees a newly-unlocked achievement with `isHidden: true`, it fires a longer-running (8 s vs default 4 s) toast with the `` icon and the localized "You unlocked a hidden achievement!" headline. The toast body reveals the real title + description for the first time so the user finally learns what they tripped — that's the reward. Public unlocks keep the existing `` toast unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../achievement-unlock-notifier.tsx | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/components/gamification/achievement-unlock-notifier.tsx b/src/components/gamification/achievement-unlock-notifier.tsx index 14047598f..4756f9f5f 100644 --- a/src/components/gamification/achievement-unlock-notifier.tsx +++ b/src/components/gamification/achievement-unlock-notifier.tsx @@ -1,7 +1,7 @@ "use client"; import { useQuery } from "@tanstack/react-query"; -import { Trophy } from "lucide-react"; +import { Sparkles, Trophy } from "lucide-react"; import { useEffect, useMemo, useRef } from "react"; import { toast } from "sonner"; import { useTranslations } from "@/lib/i18n/context"; @@ -116,10 +116,22 @@ export function AchievementUnlockNotifier({ } for (const achievement of newlyUnlocked) { - toast(t(achievement.titleKey), { - description: t(achievement.descriptionKey), - icon: , - }); + // v1.4.18 — hidden Easter-eggs get a celebration toast that + // names them "hidden". The real title/description are revealed + // *only* on the unlock toast (and afterwards on the unlocked + // card) so the surprise lands. + if (achievement.isHidden) { + toast(t("achievements.hiddenUnlockToast.title"), { + description: `${t(achievement.titleKey)} — ${t(achievement.descriptionKey)}`, + icon: , + duration: 8000, + }); + } else { + toast(t(achievement.titleKey), { + description: t(achievement.descriptionKey), + icon: , + }); + } seenIdsRef.current.add(achievement.id); }