From fe4eff0537c936fa5a5cee9b6dc49bc373fd7f2d Mon Sep 17 00:00:00 2001 From: Alissa Crane Date: Thu, 19 Sep 2024 14:45:50 -0700 Subject: [PATCH] swap toast --- src/swap/components/Swap.tsx | 33 ++++++++---- src/swap/components/SwapProvider.tsx | 5 ++ src/swap/components/SwapToast.tsx | 80 ++++++++++++++++++++++++++++ src/swap/types.ts | 2 + 4 files changed, 109 insertions(+), 11 deletions(-) create mode 100644 src/swap/components/SwapToast.tsx diff --git a/src/swap/components/Swap.tsx b/src/swap/components/Swap.tsx index 55b4826a35..2570f80e49 100644 --- a/src/swap/components/Swap.tsx +++ b/src/swap/components/Swap.tsx @@ -10,6 +10,7 @@ import { SwapMessage } from './SwapMessage'; import { SwapProvider } from './SwapProvider'; import { SwapSettings } from './SwapSettings'; import { SwapToggleButton } from './SwapToggleButton'; +import { SwapToast } from './SwapToast'; export function Swap({ children, @@ -23,17 +24,25 @@ export function Swap({ onSuccess, title = 'Swap', }: SwapReact) { - const { inputs, toggleButton, swapButton, swapMessage, swapSettings } = - useMemo(() => { - const childrenArray = Children.toArray(children); - return { - inputs: childrenArray.filter(findComponent(SwapAmountInput)), - toggleButton: childrenArray.find(findComponent(SwapToggleButton)), - swapButton: childrenArray.find(findComponent(SwapButton)), - swapMessage: childrenArray.find(findComponent(SwapMessage)), - swapSettings: childrenArray.find(findComponent(SwapSettings)), - }; - }, [children]); + const { + inputs, + toggleButton, + swapButton, + swapMessage, + swapSettings, + swapToast, + } = useMemo(() => { + const childrenArray = Children.toArray(children); + + return { + inputs: childrenArray.filter(findComponent(SwapAmountInput)), + toggleButton: childrenArray.find(findComponent(SwapToggleButton)), + swapButton: childrenArray.find(findComponent(SwapButton)), + swapMessage: childrenArray.find(findComponent(SwapMessage)), + swapSettings: childrenArray.find(findComponent(SwapSettings)), + swapToast: childrenArray.find(findComponent(SwapToast)), + }; + }, [children]); const isMounted = useIsMounted(); @@ -70,6 +79,8 @@ export function Swap({
{toggleButton}
{inputs[1]} {swapButton} + {/* swapToast wasn't registering - need to look into this */} + {Children.toArray(children)[Children.toArray(children).length - 1]}
{swapMessage}
diff --git a/src/swap/components/SwapProvider.tsx b/src/swap/components/SwapProvider.tsx index 3e19404a25..6a14b031c3 100644 --- a/src/swap/components/SwapProvider.tsx +++ b/src/swap/components/SwapProvider.tsx @@ -60,6 +60,8 @@ export function SwapProvider({ }, }); // Component lifecycle + const [isToastVisible, setIsToastVisible] = useState(false); + // Update lifecycle status, statusData will be persisted for the full lifecycle const updateLifecycleStatus = useCallback( (newStatus: LifecycleStatusUpdate) => { @@ -100,6 +102,7 @@ export function SwapProvider({ if (lifecycleStatus.statusName === 'success') { onSuccess?.(lifecycleStatus.statusData.transactionReceipt); setHasHandledSuccess(true); + setIsToastVisible(true); } // Emit Status onStatus?.(lifecycleStatus); @@ -338,6 +341,8 @@ export function SwapProvider({ lifecycleStatus, updateLifecycleStatus, to, + isToastVisible, + setIsToastVisible, }); return {children}; diff --git a/src/swap/components/SwapToast.tsx b/src/swap/components/SwapToast.tsx new file mode 100644 index 0000000000..e85830ab7b --- /dev/null +++ b/src/swap/components/SwapToast.tsx @@ -0,0 +1,80 @@ +import { ReactNode, useCallback, useEffect, useMemo } from 'react'; +import { closeSvg } from '../../internal/svg/closeSvg'; +import { background, cn, text } from '../../styles/theme'; + +import { useSwapContext } from './SwapProvider'; +import { successSvg } from '../../internal/svg/successSvg'; + +type SwapToastReact = { + className?: string; // An optional CSS class name for styling the toast component. + durationMs?: number; // An optional value to customize time until toast disappears + position?: 'top-center' | 'top-right' | 'bottom-center' | 'bottom-right'; // An optional position property to specify the toast's position on the screen. +}; + +export function SwapToast({ + className, + durationMs = 3000, + position = 'bottom-center', +}: SwapToastReact) { + const { isToastVisible, setIsToastVisible } = useSwapContext(); + + const closeToast = useCallback(() => { + setIsToastVisible(false); + }, [setIsToastVisible]); + + const positionClass = useMemo(() => { + if (position === 'bottom-right') { + return 'bottom-5 left-3/4'; + } + if (position === 'top-right') { + return 'top-[100px] left-3/4'; + } + if (position === 'top-center') { + return 'top-[100px] left-2/4'; + } + return 'bottom-5 left-2/4'; + }, [position]); + + useEffect(() => { + const timer = setTimeout(() => { + if (isToastVisible) { + setIsToastVisible(false); + } + }, durationMs); + + return () => { + if (timer) { + clearTimeout(timer); + } + }; + }, [durationMs, isToastVisible, setIsToastVisible]); + + if (!isToastVisible) { + return null; + } + + return ( +
+
+
{successSvg}
+
+ +
+ ); +} diff --git a/src/swap/types.ts b/src/swap/types.ts index c333be4f43..a433e1898a 100644 --- a/src/swap/types.ts +++ b/src/swap/types.ts @@ -205,6 +205,8 @@ export type SwapContextType = { handleToggle: () => void; updateLifecycleStatus: (state: LifecycleStatusUpdate) => void; // A function to set the lifecycle status of the component to: SwapUnit; + isToastVisible?: boolean; + setIsToastVisible?: (visible: boolean) => void; }; /**