Skip to content

Commit

Permalink
swap toast
Browse files Browse the repository at this point in the history
  • Loading branch information
alissacrane-cb committed Sep 19, 2024
1 parent a344c31 commit fe4eff0
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 11 deletions.
33 changes: 22 additions & 11 deletions src/swap/components/Swap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();

Expand Down Expand Up @@ -70,6 +79,8 @@ export function Swap({
<div className="relative h-1">{toggleButton}</div>
{inputs[1]}
{swapButton}
{/* swapToast wasn't registering - need to look into this */}
{Children.toArray(children)[Children.toArray(children).length - 1]}
<div className="flex">{swapMessage}</div>
</div>
</SwapProvider>
Expand Down
5 changes: 5 additions & 0 deletions src/swap/components/SwapProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -100,6 +102,7 @@ export function SwapProvider({
if (lifecycleStatus.statusName === 'success') {
onSuccess?.(lifecycleStatus.statusData.transactionReceipt);
setHasHandledSuccess(true);
setIsToastVisible(true);
}
// Emit Status
onStatus?.(lifecycleStatus);
Expand Down Expand Up @@ -338,6 +341,8 @@ export function SwapProvider({
lifecycleStatus,
updateLifecycleStatus,
to,
isToastVisible,
setIsToastVisible,
});

return <SwapContext.Provider value={value}>{children}</SwapContext.Provider>;
Expand Down
80 changes: 80 additions & 0 deletions src/swap/components/SwapToast.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div
className={cn(
background.default,
'flex animate-enter items-center justify-between rounded-lg',
'p-2 shadow-[0px_8px_24px_0px_rgba(0,0,0,0.12)]',
'-translate-x-2/4 fixed z-20',
positionClass,
className,
)}
>
<div className="flex items-center gap-4 p-2">
<div className={cn(text.label2, className)}>{successSvg}</div>
</div>
<button
className="p-2"
onClick={closeToast}
type="button"
data-testid="ockCloseButton"
>
{closeSvg}
</button>
</div>
);
}
2 changes: 2 additions & 0 deletions src/swap/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

/**
Expand Down

0 comments on commit fe4eff0

Please sign in to comment.