generated from nhcarrigan/template
f9c925b9fc
- Merge .codex-toast and .achievement-toast into a single .game-toast class - Fix storyToast inner class names and replace <button> wrapper with <div> - Add QuestCompleteToast and QuestFailedToast components - Add MilestoneToast for prestige, transcendence, and apotheosis events - Move shared toast container to gameLayout so all toasts stack in one column - Wire quest detection in GameContext to store full Quest objects for toast names - Trigger prestige toast from both auto-prestige and manual prestige panel
97 lines
2.4 KiB
TypeScript
97 lines
2.4 KiB
TypeScript
/**
|
|
* @file Milestone toast notification component for prestige, transcendence, and apotheosis.
|
|
* @copyright nhcarrigan
|
|
* @license Naomi's Public License
|
|
* @author Naomi Carrigan
|
|
*/
|
|
/* eslint-disable react/no-multi-comp -- Sub-components are tightly coupled to their containers */
|
|
import { type JSX, useEffect } from "react";
|
|
import { useGame } from "../../context/gameContext.js";
|
|
|
|
interface MilestoneToastItemProperties {
|
|
readonly icon: string;
|
|
readonly label: string;
|
|
readonly onDismiss: ()=> void;
|
|
}
|
|
|
|
/**
|
|
* Renders a single milestone toast notification.
|
|
* @param props - The toast item properties.
|
|
* @param props.icon - The emoji icon.
|
|
* @param props.label - The label text.
|
|
* @param props.onDismiss - Callback to dismiss the toast.
|
|
* @returns The JSX element.
|
|
*/
|
|
const MilestoneToastItem = ({
|
|
icon,
|
|
label,
|
|
onDismiss,
|
|
}: MilestoneToastItemProperties): JSX.Element => {
|
|
useEffect(() => {
|
|
const timer = setTimeout(() => {
|
|
onDismiss();
|
|
}, 4000);
|
|
return (): void => {
|
|
clearTimeout(timer);
|
|
};
|
|
}, [ onDismiss ]);
|
|
|
|
return (
|
|
<div className="game-toast" onClick={onDismiss}>
|
|
<span className="toast-icon">{icon}</span>
|
|
<div className="toast-content">
|
|
<span className="toast-label">{label}</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Renders all milestone toasts (prestige, transcendence, apotheosis).
|
|
* @returns The JSX element or null if no milestone toasts are pending.
|
|
*/
|
|
const MilestoneToast = (): JSX.Element | null => {
|
|
const {
|
|
showPrestigeToast,
|
|
showTranscendenceToast,
|
|
showApotheosisToast,
|
|
dismissPrestigeToast,
|
|
dismissTranscendenceToast,
|
|
dismissApotheosisToast,
|
|
} = useGame();
|
|
|
|
const hasAny
|
|
= showPrestigeToast || showTranscendenceToast || showApotheosisToast;
|
|
if (!hasAny) {
|
|
return null;
|
|
}
|
|
|
|
return (
|
|
<>
|
|
{showPrestigeToast
|
|
? <MilestoneToastItem
|
|
icon={"⭐"}
|
|
label={"⭐ Prestige!"}
|
|
onDismiss={dismissPrestigeToast}
|
|
/>
|
|
: null}
|
|
{showTranscendenceToast
|
|
? <MilestoneToastItem
|
|
icon={"🌌"}
|
|
label={"🌌 Transcendence!"}
|
|
onDismiss={dismissTranscendenceToast}
|
|
/>
|
|
: null}
|
|
{showApotheosisToast
|
|
? <MilestoneToastItem
|
|
icon={"✨"}
|
|
label={"✨ Apotheosis!"}
|
|
onDismiss={dismissApotheosisToast}
|
|
/>
|
|
: null}
|
|
</>
|
|
);
|
|
};
|
|
|
|
export { MilestoneToast };
|