feat(dashboard): recent-achievements card celebrates hidden unlocks

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 `<Sparkles>` 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 `<Trophy>` toast unchanged.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Marc-André BombeckandClaude Opus 4.7 committed 2026-05-10 10:34:32 +02:00
1 parent 23514b4800
commit b88f2de865
1 file changed
+17 -5
@@ -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: <Trophy className="size-4" />,
});
// 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: <Sparkles className="size-4" />,
duration: 8000,
});
} else {
toast(t(achievement.titleKey), {
description: t(achievement.descriptionKey),
icon: <Trophy className="size-4" />,
});
}
seenIdsRef.current.add(achievement.id);
}