Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

swap toast #1281

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
83 changes: 83 additions & 0 deletions src/swap/components/SwapToast.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { ReactNode, useCallback, useEffect, useMemo } from 'react';
import { closeSvg } from '../../internal/svg/closeSvg';
import { background, cn, color, 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>
<div className={cn(text.label1, 'text-nowrap', className)}>
<p className={color.foreground}>Successful!</p>
</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
Loading