From 9aa058a043cf9dd53565299a66c0990af12f2cf1 Mon Sep 17 00:00:00 2001 From: Todd Kao Date: Thu, 19 Sep 2024 17:23:48 -0400 Subject: [PATCH 1/2] Add themeAtom to fix theme in modals --- packages/widget-v2/src/components/Modal.tsx | 5 ++++- packages/widget-v2/src/state/skipClient.ts | 3 +++ packages/widget-v2/src/widget/Widget.tsx | 12 ++++++++---- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/packages/widget-v2/src/components/Modal.tsx b/packages/widget-v2/src/components/Modal.tsx index aa41e0b9..cf048552 100644 --- a/packages/widget-v2/src/components/Modal.tsx +++ b/packages/widget-v2/src/components/Modal.tsx @@ -9,6 +9,7 @@ import { ErrorBoundary } from "react-error-boundary"; import { useAtom } from "jotai"; import { errorAtom, ErrorType } from "@/state/errorPage"; import { numberOfModalsOpenAtom } from "@/state/modal"; +import { themeAtom } from "@/state/skipClient"; export type ModalProps = { children: React.ReactNode; @@ -73,6 +74,7 @@ export const useModal = ( modal?: FC, initialArgs?: Partial ) => { + const [theme] = useAtom(themeAtom); const [numberOfModalsOpen, setNumberOfModalsOpen] = useAtom( numberOfModalsOpenAtom ); @@ -86,6 +88,7 @@ export const useModal = ( modalInstance.show({ stackedModal: numberOfModalsOpen > 0, ...showArgs, + theme, } as Partial); setNumberOfModalsOpen((prev) => prev + 1); }, @@ -98,7 +101,7 @@ export const useModal = ( modalInstance.hide(); }, }), - [modalInstance, setNumberOfModalsOpen, numberOfModalsOpen] + [modalInstance, theme, numberOfModalsOpen, setNumberOfModalsOpen] ); }; diff --git a/packages/widget-v2/src/state/skipClient.ts b/packages/widget-v2/src/state/skipClient.ts index 65679f83..d518628e 100644 --- a/packages/widget-v2/src/state/skipClient.ts +++ b/packages/widget-v2/src/state/skipClient.ts @@ -18,12 +18,15 @@ import { swapDirectionAtom, } from "./swapPage"; import { getAmountWei } from "@/utils/number"; +import { defaultTheme, Theme } from "@/widget/theme"; export const skipClientConfigAtom = atom({ apiURL, endpointOptions, }); +export const themeAtom = atom(defaultTheme); + export const skipClient = atom((get) => { const options = get(skipClientConfigAtom); return new SkipClient(options); diff --git a/packages/widget-v2/src/widget/Widget.tsx b/packages/widget-v2/src/widget/Widget.tsx index 3cd91e97..f6365c67 100644 --- a/packages/widget-v2/src/widget/Widget.tsx +++ b/packages/widget-v2/src/widget/Widget.tsx @@ -3,12 +3,12 @@ import NiceModal from "@ebay/nice-modal-react"; import { styled } from "styled-components"; import { createModal, useModal } from "@/components/Modal"; import { cloneElement, ReactElement, useEffect } from "react"; -import { PartialTheme } from "./theme"; +import { defaultTheme, PartialTheme } from "./theme"; import { Router } from "./Router"; import { useResetAtom } from "jotai/utils"; import { numberOfModalsOpenAtom } from "@/state/modal"; import { useSetAtom } from "jotai"; -import { skipClientConfigAtom } from "@/state/skipClient"; +import { skipClientConfigAtom, themeAtom } from "@/state/skipClient"; import { SkipClientOptions } from "@skip-go/client"; export type SwapWidgetProps = { @@ -17,9 +17,11 @@ export type SwapWidgetProps = { export const SwapWidget = ({ theme, ...skipClientConfig }: SwapWidgetProps) => { const setSkipClientConfig = useSetAtom(skipClientConfigAtom); + const setTheme = useSetAtom(themeAtom); useEffect(() => { setSkipClientConfig(skipClientConfig); - }, [setSkipClientConfig, skipClientConfig]); + setTheme({ ...defaultTheme, ...theme }); + }, [setSkipClientConfig, setTheme, skipClientConfig, theme]); return ( @@ -34,9 +36,11 @@ export const SwapWidget = ({ theme, ...skipClientConfig }: SwapWidgetProps) => { const SwapWidgetWithoutNiceModalProvider = ({ theme, ...skipClientConfig }: SwapWidgetProps) => { const setSkipClientConfig = useSetAtom(skipClientConfigAtom); + const setTheme = useSetAtom(themeAtom); useEffect(() => { setSkipClientConfig(skipClientConfig); - }, [setSkipClientConfig, skipClientConfig]); + setTheme({ ...defaultTheme, ...theme }); + }, [setSkipClientConfig, setTheme, skipClientConfig, theme]); return ( From 8b5c61ab915bd6f3692e83895fbee0084071e79c Mon Sep 17 00:00:00 2001 From: Todd Kao Date: Thu, 19 Sep 2024 17:31:18 -0400 Subject: [PATCH 2/2] Fix SwapDetailModal for light theme, Fix widget.stories rerendering --- .../src/pages/SwapPage/SwapDetailModal.tsx | 111 +++++++++++------- .../widget-v2/src/stories/Widget.stories.tsx | 8 +- 2 files changed, 72 insertions(+), 47 deletions(-) diff --git a/packages/widget-v2/src/pages/SwapPage/SwapDetailModal.tsx b/packages/widget-v2/src/pages/SwapPage/SwapDetailModal.tsx index cf1f72a4..a1a3af32 100644 --- a/packages/widget-v2/src/pages/SwapPage/SwapDetailModal.tsx +++ b/packages/widget-v2/src/pages/SwapPage/SwapDetailModal.tsx @@ -12,51 +12,66 @@ import { formatUSD } from "@/utils/intl"; import { SLIPPAGE_OPTIONS } from "@/constants/widget"; import { getClientOperations, OperationType } from "@/utils/clientType"; import { convertTokenAmountToHumanReadableAmount } from "@/utils/crypto"; +import { getBrandButtonTextColor } from "@/utils/colors"; export const SwapDetailModal = createModal((modalProps: ModalProps) => { const { data: route } = useAtomValue(skipRouteAtom); const { data: chains } = useAtomValue(skipChainsAtom); const [swapSettings, setSwapSettings] = useAtom(swapSettingsAtom); const chainsRoute = useMemo(() => { - return route?.chainIDs.map((chainID) => chains?.find((chain) => chain.chainID === chainID)); + return route?.chainIDs.map((chainID) => + chains?.find((chain) => chain.chainID === chainID) + ); }, [route, chains]); const clientOperations = route && getClientOperations(route.operations); const axelarTransferOperation = useMemo(() => { if (!clientOperations) return; - return clientOperations?.find((item) => item.type === OperationType.axelarTransfer); + return clientOperations?.find( + (item) => item.type === OperationType.axelarTransfer + ); }, [clientOperations]); const hyperlaneTransferOperation = useMemo(() => { if (!clientOperations) return; - return clientOperations?.find((item) => item.type === OperationType.hyperlaneTransfer); + return clientOperations?.find( + (item) => item.type === OperationType.hyperlaneTransfer + ); }, [clientOperations]); const axelarFee = useMemo(() => { if (axelarTransferOperation) { - const { feeAmount, feeAsset, usdFeeAmount } = - axelarTransferOperation; + const { feeAmount, feeAsset, usdFeeAmount } = axelarTransferOperation; if (!feeAmount || !feeAsset || !feeAsset.decimals) return; - const computed = convertTokenAmountToHumanReadableAmount(feeAmount, feeAsset.decimals); + const computed = convertTokenAmountToHumanReadableAmount( + feeAmount, + feeAsset.decimals + ); return { assetAmount: Number(computed), formattedAssetAmount: `${computed} ${feeAsset.symbol}`, - formattedUsdAmount: usdFeeAmount ? `${formatUSD(usdFeeAmount)}` : undefined + formattedUsdAmount: usdFeeAmount + ? `${formatUSD(usdFeeAmount)}` + : undefined, }; } }, [axelarTransferOperation]); const hyperlaneFee = useMemo(() => { if (hyperlaneTransferOperation) { - const { feeAmount, feeAsset, usdFeeAmount } = - hyperlaneTransferOperation; + const { feeAmount, feeAsset, usdFeeAmount } = hyperlaneTransferOperation; if (!feeAmount || !feeAsset || !feeAsset.decimals) return; - const computed = convertTokenAmountToHumanReadableAmount(feeAmount, feeAsset.decimals); + const computed = convertTokenAmountToHumanReadableAmount( + feeAmount, + feeAsset.decimals + ); return { assetAmount: Number(computed), formattedAssetAmount: `${computed} ${feeAsset.symbol}`, - formattedUsdAmount: usdFeeAmount ? `${formatUSD(usdFeeAmount)}` : undefined + formattedUsdAmount: usdFeeAmount + ? `${formatUSD(usdFeeAmount)}` + : undefined, }; } }, [hyperlaneTransferOperation]); @@ -92,7 +107,7 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => { return { assetAmount: Number(inAsset), formattedAssetAmount: `${inAsset} ${fee[0].originAsset.symbol}`, - formattedUsdAmount: `${formatUSD(computedUsd)}` + formattedUsdAmount: `${formatUSD(computedUsd)}`, }; }, [isSmartRelay, route?.estimatedFees]); @@ -104,11 +119,7 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => { {chainsRoute?.map((chain, index) => ( <> - + {index !== chainsRoute.length - 1 && ( )} @@ -120,7 +131,9 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => { Price Impact - {route?.swapPriceImpactPercent}% + + {route?.swapPriceImpactPercent}% + )} @@ -139,30 +152,37 @@ export const SwapDetailModal = createModal((modalProps: ModalProps) => { - { - (axelarFee || hyperlaneFee || smartRelayFee) && ( - - {axelarFee && ( - - Axelar Bridging Fee - {axelarFee.formattedAssetAmount} ({axelarFee.formattedUsdAmount}) - - )} - {hyperlaneFee && ( - - Hyperlane Bridging Fee - {hyperlaneFee.formattedAssetAmount} ({hyperlaneFee.formattedUsdAmount}) - - )} - {smartRelayFee && ( - - Relayer Fee - {smartRelayFee.formattedAssetAmount} ({smartRelayFee.formattedUsdAmount}) - - )} - - ) - } + {(axelarFee || hyperlaneFee || smartRelayFee) && ( + + {axelarFee && ( + + Axelar Bridging Fee + + {axelarFee.formattedAssetAmount} ({axelarFee.formattedUsdAmount} + ) + + + )} + {hyperlaneFee && ( + + Hyperlane Bridging Fee + + {hyperlaneFee.formattedAssetAmount} ( + {hyperlaneFee.formattedUsdAmount}) + + + )} + {smartRelayFee && ( + + Relayer Fee + + {smartRelayFee.formattedAssetAmount} ( + {smartRelayFee.formattedUsdAmount}) + + + )} + + )} @@ -182,9 +202,12 @@ const StyledSlippageOptionLabel = styled(SmallText) <{ selected?: boolean }>` border-radius: 7px; padding: 4px 7px; white-space: nowrap; - color: ${(props) => props.theme.primary.text.normal}; + color: ${({ selected, theme }) => + selected + ? getBrandButtonTextColor(theme.brandColor) + : theme.primary.text.normal}; &:hover { - box-shadow:inset 0px 0px 0px 1px ${(props) => props.theme.brandColor}; + box-shadow: inset 0px 0px 0px 1px ${(props) => props.theme.brandColor}; opacity: 1; cursor: pointer; } diff --git a/packages/widget-v2/src/stories/Widget.stories.tsx b/packages/widget-v2/src/stories/Widget.stories.tsx index 2056931a..04880af3 100644 --- a/packages/widget-v2/src/stories/Widget.stories.tsx +++ b/packages/widget-v2/src/stories/Widget.stories.tsx @@ -3,7 +3,7 @@ import { ShowSwapWidget, SwapWidget, SwapWidgetProps } from "@/widget/Widget"; import { defaultTheme, lightTheme, Theme } from "@/widget/theme"; import NiceModal from "@ebay/nice-modal-react"; import { styled } from "styled-components"; -import { ReactElement, useEffect } from "react"; +import { ReactElement, useEffect, useMemo } from "react"; import { destinationAssetAtom, sourceAssetAmountAtom, sourceAssetAtom } from "@/state/swapPage"; import { useAtom, useSetAtom } from "jotai"; import { skipAssetsAtom } from "@/state/skipClient"; @@ -29,13 +29,15 @@ export const Widget = (props: Props) => { setSourceAssetAmount("1"); }, [destinationAsset, setDestinationAsset, setSourceAsset, setSourceAssetAmount, sourceAsset]); - return ; + return useMemo(() => { + return ; + }, [props]); }; export const Modal = (props: Props) => { return ( - + ); };