-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
178 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/pages/advent-calendar-2024/components/toast-wrapper.jsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { useState, useEffect } from "react"; | ||
import Toast from "./toast"; // Assuming your Toast component is already implemented | ||
|
||
const ToastWrapper = ({ toasts, removeToast }) => { | ||
return ( | ||
<div | ||
style={{ | ||
position: "absolute", | ||
bottom: "16px", | ||
right: "16px", | ||
}} | ||
> | ||
<div style={{ position: "relative" }}> | ||
{toasts.map((toast, index) => ( | ||
<Toast | ||
id={toast.id} | ||
key={toast.id} | ||
title={toast.name} | ||
description={toast.message} | ||
icon={toast.icon} | ||
onClose={() => removeToast(toast.id)} // Dismiss the toast by `id` | ||
/> | ||
))} | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default ToastWrapper; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import { useEffect, useState, useRef } from "react"; | ||
import { | ||
Stack, | ||
Text3, | ||
Text2, | ||
skinVars, | ||
Inline, | ||
ButtonLink, | ||
IconButton, | ||
IconCloseRegular, | ||
} from "@telefonica/mistica"; | ||
|
||
const Toast = ({ | ||
title, | ||
description, | ||
icon: Icon, | ||
duration = 3000, | ||
style, | ||
onClose, | ||
}) => { | ||
const [visible, setVisible] = useState(true); | ||
const [isHovered, setIsHovered] = useState(false); | ||
const timeoutRef = useRef(null); | ||
|
||
const clearHideTimeout = () => { | ||
if (timeoutRef.current) { | ||
clearTimeout(timeoutRef.current); | ||
timeoutRef.current = null; | ||
} | ||
}; | ||
|
||
const startHideTimeout = () => { | ||
clearHideTimeout(); | ||
timeoutRef.current = setTimeout(() => { | ||
setVisible(false); // This will trigger unmount if necessary | ||
onClose?.(); // Pass the ID to remove the toast | ||
}, duration); | ||
}; | ||
|
||
useEffect(() => { | ||
if (!isHovered) { | ||
startHideTimeout(); // Start timeout when not hovered | ||
} else { | ||
clearHideTimeout(); // Clear timeout when hovered | ||
} | ||
|
||
return () => clearHideTimeout(); // Cleanup timeout on unmount | ||
}, [isHovered, duration]); | ||
|
||
// Always render dismiss button, regardless of toast visibility | ||
const handleDismiss = () => { | ||
setVisible(false); | ||
clearHideTimeout(); | ||
onClose?.(); // Ensure it triggers onClose from parent | ||
}; | ||
|
||
if (!visible) return null; // Hide toast when not visible | ||
|
||
return ( | ||
<div | ||
style={{ | ||
background: skinVars.colors.background, | ||
padding: "24px", | ||
borderRadius: "8px", | ||
border: `2px solid ${skinVars.colors.border}`, | ||
zIndex: 1000, | ||
width: 480, | ||
position: "relative", // Ensures dismiss button is on top | ||
...style, | ||
}} | ||
onMouseEnter={() => setIsHovered(true)} | ||
onMouseLeave={() => setIsHovered(false)} | ||
> | ||
<Inline space={16}> | ||
<div | ||
style={{ | ||
background: | ||
"linear-gradient(120deg, rgba(255,249,208,1) 0%, rgba(255,178,178,1) 24%, rgba(59,95,253,1) 66%, rgba(255,99,114,1) 100%)", | ||
padding: "16px", | ||
display: "inline-flex", | ||
justifyContent: "center", | ||
alignItems: "center", | ||
borderRadius: "8px", | ||
outline: `1px solid ${skinVars.colors.inverse}`, | ||
outlineOffset: "-4px", | ||
position: "relative", | ||
}} | ||
> | ||
<Icon color={skinVars.colors.inverse} /> | ||
</div> | ||
<Stack space={8}> | ||
<Text2 weight="bold">Achievement unlocked</Text2> | ||
<Text3 weight="bold">{title}</Text3> | ||
<Text3>{description}</Text3> | ||
<ButtonLink bleedLeft to={"/advent-calendar-2024/progress-view"}> | ||
View progress | ||
</ButtonLink> | ||
</Stack> | ||
{/* Dismiss button should always be on top */} | ||
<div style={{ position: "absolute", top: 8, right: 8 }}> | ||
<IconButton | ||
Icon={IconCloseRegular} | ||
onPress={handleDismiss} // Handle dismiss in the component itself | ||
/> | ||
</div> | ||
</Inline> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Toast; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters