From 00121bd85a8132cecf0cf8466b916a516cb17d33 Mon Sep 17 00:00:00 2001 From: Alissa Crane Date: Thu, 19 Sep 2024 14:45:50 -0700 Subject: [PATCH 01/10] 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 ec91f772c5..2127b88b4f 100644 --- a/src/swap/components/SwapProvider.tsx +++ b/src/swap/components/SwapProvider.tsx @@ -70,6 +70,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) => { @@ -117,6 +119,7 @@ export function SwapProvider({ if (lifecycleStatus.statusName === 'success') { onSuccess?.(lifecycleStatus.statusData.transactionReceipt); setHasHandledSuccess(true); + setIsToastVisible(true); } // Emit Status onStatus?.(lifecycleStatus); @@ -378,6 +381,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 b99811b0c7..28c429db73 100644 --- a/src/swap/types.ts +++ b/src/swap/types.ts @@ -213,6 +213,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; }; /** From d06c24c8ab7f1f3639f69426bc03469a55e677c5 Mon Sep 17 00:00:00 2001 From: Alissa Crane Date: Thu, 19 Sep 2024 14:48:41 -0700 Subject: [PATCH 02/10] add label --- src/swap/components/SwapToast.tsx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/swap/components/SwapToast.tsx b/src/swap/components/SwapToast.tsx index e85830ab7b..3e6cf5611d 100644 --- a/src/swap/components/SwapToast.tsx +++ b/src/swap/components/SwapToast.tsx @@ -1,6 +1,6 @@ import { ReactNode, useCallback, useEffect, useMemo } from 'react'; import { closeSvg } from '../../internal/svg/closeSvg'; -import { background, cn, text } from '../../styles/theme'; +import { background, cn, color, text } from '../../styles/theme'; import { useSwapContext } from './SwapProvider'; import { successSvg } from '../../internal/svg/successSvg'; @@ -19,7 +19,7 @@ export function SwapToast({ const { isToastVisible, setIsToastVisible } = useSwapContext(); const closeToast = useCallback(() => { - setIsToastVisible(false); + setIsToastVisible?.(false); }, [setIsToastVisible]); const positionClass = useMemo(() => { @@ -38,7 +38,7 @@ export function SwapToast({ useEffect(() => { const timer = setTimeout(() => { if (isToastVisible) { - setIsToastVisible(false); + setIsToastVisible?.(false); } }, durationMs); @@ -67,6 +67,9 @@ export function SwapToast({
{successSvg}
+
+

Successful!

+