From b0ac857ade1aeb548c89e593d308a6f0491fea65 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Mon, 23 Mar 2026 16:06:51 +0000 Subject: [PATCH 1/8] feat: new send to wallet functionality --- .../components/AmountInput/AmountInput.tsx | 15 +- .../AmountInputAdornment.style.tsx | 69 ------ .../AmountInputEndAdornment.style.ts | 12 + .../AmountInput/AmountInputEndAdornment.tsx | 42 ++-- .../src/components/ButtonChip/ButtonChip.tsx | 10 + .../ReverseTokensButton.tsx | 11 +- .../src/components/SelectChainAndToken.tsx | 46 +--- .../SelectTokenButton.style.tsx | 104 +++----- .../SelectTokenButton/SelectTokenButton.tsx | 20 +- .../SendToWallet/SendToWallet.style.tsx | 55 ----- .../components/SendToWallet/SendToWallet.tsx | 32 +++ .../SendToWallet/SendToWalletButton.tsx | 229 +++++++----------- .../SendToWallet/SendToWalletExpandButton.tsx | 63 ----- .../src/hooks/useToAddressAutoPopulate.ts | 4 - .../widget/src/hooks/useToAddressReset.ts | 24 +- packages/widget/src/i18n/en.json | 4 +- .../widget/src/pages/MainPage/MainPage.tsx | 31 +-- .../src/pages/SendToWallet/BookmarksPage.tsx | 3 - .../SendToWallet/ConfirmAddressSheet.tsx | 4 - .../SendToWallet/ConnectedWalletsPage.tsx | 3 - .../pages/SendToWallet/RecentWalletsPage.tsx | 3 - .../widget/src/stores/form/FormUpdater.tsx | 6 - .../stores/form/URLSearchParamsBuilder.tsx | 4 - packages/widget/src/stores/form/useFormRef.ts | 13 +- packages/widget/src/stores/settings/types.ts | 8 - .../stores/settings/useSendToWalletStore.ts | 25 -- 26 files changed, 231 insertions(+), 609 deletions(-) delete mode 100644 packages/widget/src/components/AmountInput/AmountInputAdornment.style.tsx create mode 100644 packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts create mode 100644 packages/widget/src/components/ButtonChip/ButtonChip.tsx delete mode 100644 packages/widget/src/components/SendToWallet/SendToWallet.style.tsx create mode 100644 packages/widget/src/components/SendToWallet/SendToWallet.tsx delete mode 100644 packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx delete mode 100644 packages/widget/src/stores/settings/useSendToWalletStore.ts diff --git a/packages/widget/src/components/AmountInput/AmountInput.tsx b/packages/widget/src/components/AmountInput/AmountInput.tsx index 3c463c4c9..f8bf82721 100644 --- a/packages/widget/src/components/AmountInput/AmountInput.tsx +++ b/packages/widget/src/components/AmountInput/AmountInput.tsx @@ -18,6 +18,7 @@ import { } from '../../utils/format.js' import { fitInputText } from '../../utils/input.js' import { InputCard } from '../Card/InputCard.js' +import { SendToWallet } from '../SendToWallet/SendToWallet.js' import { AmountInputCardHeader, AmountInputCardTitle, @@ -31,10 +32,7 @@ import { AmountInputEndAdornment } from './AmountInputEndAdornment.js' import { AmountInputStartAdornment } from './AmountInputStartAdornment.js' import { PriceFormHelperText } from './PriceFormHelperText.js' -export const AmountInput: React.FC = ({ - formType, - ...props -}) => { +export const AmountInput: React.FC = ({ formType }) => { const { disabledUI } = useWidgetConfig() const [chainId, tokenAddress] = useFieldValues( @@ -49,12 +47,9 @@ export const AmountInput: React.FC = ({ : undefined - } + endAdornment={} bottomAdornment={} disabled={disabled} - {...props} /> ) } @@ -75,7 +70,6 @@ const AmountInputBase: React.FC< endAdornment, bottomAdornment, disabled, - ...props }) => { const { t } = useTranslation() const { subvariant, subvariantOptions } = useWidgetConfig() @@ -171,7 +165,7 @@ const AmountInputBase: React.FC< : t('header.send') return ( - + {title} {endAdornment} @@ -204,6 +198,7 @@ const AmountInputBase: React.FC< {bottomAdornment} + {!disabled && } ) } diff --git a/packages/widget/src/components/AmountInput/AmountInputAdornment.style.tsx b/packages/widget/src/components/AmountInput/AmountInputAdornment.style.tsx deleted file mode 100644 index a596e3a14..000000000 --- a/packages/widget/src/components/AmountInput/AmountInputAdornment.style.tsx +++ /dev/null @@ -1,69 +0,0 @@ -import { Box, styled } from '@mui/material' -import { cardClasses } from '@mui/material/Card' -import { ButtonTertiary } from '../ButtonTertiary.js' - -export const ButtonContainer = styled(Box)(({ theme }) => ({ - display: 'flex', - gap: theme.spacing(0.5), -})) - -export const MaxButton = styled(ButtonTertiary)(({ theme }) => ({ - padding: theme.spacing(0.5, 1, 0.5, 1), - margin: theme.spacing(0, 0, 0, 0.5), - lineHeight: 1, - fontSize: '0.75rem', - minWidth: 'unset', - height: 24, - opacity: 0, - transform: 'scale(0.85) translateY(-10px)', - transition: - 'opacity 200ms cubic-bezier(0.4, 0, 0.2, 1), transform 200ms cubic-bezier(0.4, 0, 0.2, 1)', - '&[data-delay="0"]': { - [`.${cardClasses.root}:hover &`]: { - opacity: 1, - transform: 'scale(1) translateY(0)', - transitionDelay: '75ms', - }, - [`.${cardClasses.root}:not(:hover) &`]: { - opacity: 0, - transform: 'scale(0.85) translateY(-10px)', - transitionDelay: '0ms', - }, - }, - '&[data-delay="1"]': { - [`.${cardClasses.root}:hover &`]: { - opacity: 1, - transform: 'scale(1) translateY(0)', - transitionDelay: '50ms', - }, - [`.${cardClasses.root}:not(:hover) &`]: { - opacity: 0, - transform: 'scale(0.85) translateY(-10px)', - transitionDelay: '25ms', - }, - }, - '&[data-delay="2"]': { - [`.${cardClasses.root}:hover &`]: { - opacity: 1, - transform: 'scale(1) translateY(0)', - transitionDelay: '25ms', - }, - [`.${cardClasses.root}:not(:hover) &`]: { - opacity: 0, - transform: 'scale(0.85) translateY(-10px)', - transitionDelay: '50ms', - }, - }, - '&[data-delay="3"]': { - [`.${cardClasses.root}:hover &`]: { - opacity: 1, - transform: 'scale(1) translateY(0)', - transitionDelay: '0ms', - }, - [`.${cardClasses.root}:not(:hover) &`]: { - opacity: 0, - transform: 'scale(0.85) translateY(-10px)', - transitionDelay: '75ms', - }, - }, -})) diff --git a/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts new file mode 100644 index 000000000..1842f493c --- /dev/null +++ b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts @@ -0,0 +1,12 @@ +import { Box, styled } from '@mui/material' +import { ButtonChip } from '../ButtonChip/ButtonChip.js' + +export const ButtonContainer = styled(Box)(({ theme }) => ({ + display: 'flex', + gap: theme.spacing(1), + padding: theme.spacing(0, 2, 2, 2), +})) + +export const AmountInputButton = styled(ButtonChip)(() => ({ + flex: 1, +})) diff --git a/packages/widget/src/components/AmountInput/AmountInputEndAdornment.tsx b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.tsx index 0bc4ab1d5..182eb4a7c 100644 --- a/packages/widget/src/components/AmountInput/AmountInputEndAdornment.tsx +++ b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.tsx @@ -1,5 +1,4 @@ import { formatUnits } from '@lifi/sdk' -import { InputAdornment } from '@mui/material' import { memo } from 'react' import { useTranslation } from 'react-i18next' import { useAvailableChains } from '../../hooks/useAvailableChains.js' @@ -9,7 +8,10 @@ import type { FormTypeProps } from '../../stores/form/types.js' import { FormKeyHelper } from '../../stores/form/types.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { useFieldValues } from '../../stores/form/useFieldValues.js' -import { ButtonContainer, MaxButton } from './AmountInputAdornment.style.js' +import { + AmountInputButton, + ButtonContainer, +} from './AmountInputEndAdornment.style.js' export const AmountInputEndAdornment = memo(({ formType }: FormTypeProps) => { const { t } = useTranslation() @@ -69,24 +71,24 @@ export const AmountInputEndAdornment = memo(({ formType }: FormTypeProps) => { } } + if (formType !== 'from' || !token?.amount) { + return null + } + return ( - - {formType === 'from' && token?.amount ? ( - - handlePercentage(25)} data-delay="0"> - 25% - - handlePercentage(50)} data-delay="1"> - 50% - - handlePercentage(75)} data-delay="2"> - 75% - - - {t('button.max')} - - - ) : null} - + + handlePercentage(25)}> + 25% + + handlePercentage(50)}> + 50% + + handlePercentage(75)}> + 75% + + + {t('button.max')} + + ) }) diff --git a/packages/widget/src/components/ButtonChip/ButtonChip.tsx b/packages/widget/src/components/ButtonChip/ButtonChip.tsx new file mode 100644 index 000000000..725e765db --- /dev/null +++ b/packages/widget/src/components/ButtonChip/ButtonChip.tsx @@ -0,0 +1,10 @@ +import { styled } from '@mui/material' +import { ButtonTertiary } from '../ButtonTertiary.js' + +export const ButtonChip = styled(ButtonTertiary)(({ theme }) => ({ + padding: theme.spacing(0.5, 1.5), + fontSize: 12, + fontWeight: 700, + lineHeight: 1.3334, + height: 'auto', +})) diff --git a/packages/widget/src/components/ReverseTokensButton/ReverseTokensButton.tsx b/packages/widget/src/components/ReverseTokensButton/ReverseTokensButton.tsx index d2f776532..25a34f19c 100644 --- a/packages/widget/src/components/ReverseTokensButton/ReverseTokensButton.tsx +++ b/packages/widget/src/components/ReverseTokensButton/ReverseTokensButton.tsx @@ -1,4 +1,3 @@ -import ArrowDownward from '@mui/icons-material/ArrowDownward' import ArrowForward from '@mui/icons-material/ArrowForward' import { useAvailableChains } from '../../hooks/useAvailableChains.js' import { useToAddressAutoPopulate } from '../../hooks/useToAddressAutoPopulate.js' @@ -6,9 +5,7 @@ import { useToAddressReset } from '../../hooks/useToAddressReset.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { IconCard, ReverseContainer } from './ReverseTokensButton.style.js' -export const ReverseTokensButton: React.FC<{ vertical?: boolean }> = ({ - vertical, -}) => { +export const ReverseTokensButton = () => { const { setFieldValue, getFieldValues } = useFieldActions() const { getChainById } = useAvailableChains() const { tryResetToAddress } = useToAddressReset() @@ -53,11 +50,7 @@ export const ReverseTokensButton: React.FC<{ vertical?: boolean }> = ({ return ( - {vertical ? ( - - ) : ( - - )} + ) diff --git a/packages/widget/src/components/SelectChainAndToken.tsx b/packages/widget/src/components/SelectChainAndToken.tsx index 1cfdc3317..7ba63ad26 100644 --- a/packages/widget/src/components/SelectChainAndToken.tsx +++ b/packages/widget/src/components/SelectChainAndToken.tsx @@ -1,25 +1,13 @@ -import type { BoxProps, Theme } from '@mui/material' -import { Box, useMediaQuery } from '@mui/material' +import { Box } from '@mui/material' import { ReverseTokensButton } from '../components/ReverseTokensButton/ReverseTokensButton.js' import { SelectTokenButton } from '../components/SelectTokenButton/SelectTokenButton.js' import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js' -import { useFieldValues } from '../stores/form/useFieldValues.js' import { DisabledUI, HiddenUI } from '../types/widget.js' import { ReverseTokensButtonEmpty } from './ReverseTokensButton/ReverseTokensButton.style.js' -export const SelectChainAndToken: React.FC = (props) => { - const prefersNarrowView = useMediaQuery((theme: Theme) => - theme.breakpoints.down('sm') - ) +export const SelectChainAndToken = () => { const { disabledUI, hiddenUI, subvariant } = useWidgetConfig() - const [fromChain, toChain, fromToken, toToken] = useFieldValues( - 'fromChain', - 'toChain', - 'fromToken', - 'toToken' - ) - const hiddenReverse = subvariant === 'refuel' || disabledUI?.includes(DisabledUI.FromToken) || @@ -32,40 +20,22 @@ export const SelectChainAndToken: React.FC = (props) => { const hiddenToToken = subvariant === 'custom' || hiddenUI?.includes(HiddenUI.ToToken) - const isCompact = - !!fromChain && - !!toChain && - !!fromToken && - !!toToken && - !prefersNarrowView && - !hiddenToToken && - !hiddenFromToken + const showReverseButton = !hiddenToToken && !hiddenFromToken return ( - + {!hiddenFromToken ? ( - + ) : null} - {!hiddenToToken && !hiddenFromToken ? ( + {showReverseButton ? ( !hiddenReverse ? ( - + ) : ( ) ) : null} {!hiddenToToken ? ( - + ) : null} ) diff --git a/packages/widget/src/components/SelectTokenButton/SelectTokenButton.style.tsx b/packages/widget/src/components/SelectTokenButton/SelectTokenButton.style.tsx index cda1e94c0..edc697f6a 100644 --- a/packages/widget/src/components/SelectTokenButton/SelectTokenButton.style.tsx +++ b/packages/widget/src/components/SelectTokenButton/SelectTokenButton.style.tsx @@ -7,70 +7,39 @@ import type { FormType } from '../../stores/form/types.js' import { Card } from '../Card/Card.js' import { CardHeader } from '../Card/CardHeader.js' +const truncate = { + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + width: 96, +} + export const SelectTokenCardHeader = styled(CardHeader, { - shouldForwardProp: (prop) => - !['selected', 'compact'].includes(prop as string), -})<{ selected?: boolean; compact?: boolean }>( - ({ theme, selected, compact }) => ({ - padding: theme.spacing(2), - [`.${cardHeaderClasses.title}`]: { - color: theme.vars.palette.text.secondary, - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - width: 256, - fontSize: compact && !selected ? 16 : 18, - fontWeight: 500, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 224, - }, - [theme.breakpoints.down(theme.breakpoints.values.xs)]: { - width: 180, - fontSize: 16, - }, - }, - [`.${cardHeaderClasses.subheader}`]: { - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - width: 256, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 224, - }, - [theme.breakpoints.down(theme.breakpoints.values.xs)]: { - width: 180, - }, - }, - variants: [ - { - props: ({ selected }) => selected, - style: { - [`.${cardHeaderClasses.title}`]: { - color: theme.vars.palette.text.primary, - fontWeight: 600, - }, - }, - }, - { - props: ({ compact }) => compact, - style: { - [`.${cardHeaderClasses.title}`]: { - width: 96, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 96, - }, - }, - [`.${cardHeaderClasses.subheader}`]: { - width: 96, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 96, - }, - }, + shouldForwardProp: (prop) => !['selected'].includes(prop as string), +})<{ selected?: boolean }>(({ theme }) => ({ + padding: theme.spacing(2), + [`.${cardHeaderClasses.title}`]: { + ...truncate, + color: theme.vars.palette.text.secondary, + fontSize: 16, + fontWeight: 500, + }, + [`.${cardHeaderClasses.subheader}`]: { + ...truncate, + }, + variants: [ + { + props: ({ selected }) => selected, + style: { + [`.${cardHeaderClasses.title}`]: { + color: theme.vars.palette.text.primary, + fontSize: 18, + fontWeight: 600, }, }, - ], - }) -) + }, + ], +})) export const SelectTokenCard = styled(Card)(({ theme }) => { const cardVariant = theme.components?.MuiCard?.defaultProps?.variant @@ -87,14 +56,11 @@ export const SelectTokenCard = styled(Card)(({ theme }) => { }) export const CardContent = styled(MuiCardContent, { - shouldForwardProp: (prop) => - !['formType', 'compact', 'mask'].includes(prop as string), -})<{ formType: FormType; compact: boolean; mask?: boolean }>( - ({ theme, formType, compact, mask = true }) => { + shouldForwardProp: (prop) => !['formType', 'mask'].includes(prop as string), +})<{ formType: FormType; mask?: boolean }>( + ({ theme, formType, mask = true }) => { const cardVariant = theme.components?.MuiCard?.defaultProps?.variant - const direction = formType === 'to' ? '-8px' : 'calc(100% + 8px)' - const horizontal = compact ? direction : '50%' - const vertical = compact ? '50%' : direction + const horizontal = formType === 'to' ? '-8px' : 'calc(100% + 8px)' return { padding: 0, transition: theme.transitions.create(['background-color'], { @@ -107,7 +73,7 @@ export const CardContent = styled(MuiCardContent, { ...(cardVariant !== 'outlined' && { backgroundColor: theme.vars.palette.background.paper, mask: mask - ? `radial-gradient(circle 20px at ${horizontal} ${vertical}, #fff0 96%, #fff) 100% 100% / 100% 100% no-repeat` + ? `radial-gradient(circle 20px at ${horizontal} 50%, #fff0 96%, #fff) 100% 100% / 100% 100% no-repeat` : 'none', }), ...(cardVariant === 'filled' && { diff --git a/packages/widget/src/components/SelectTokenButton/SelectTokenButton.tsx b/packages/widget/src/components/SelectTokenButton/SelectTokenButton.tsx index ad8e3ea86..87894d9c1 100644 --- a/packages/widget/src/components/SelectTokenButton/SelectTokenButton.tsx +++ b/packages/widget/src/components/SelectTokenButton/SelectTokenButton.tsx @@ -2,7 +2,6 @@ import { Skeleton } from '@mui/material' import { useNavigate } from '@tanstack/react-router' import { useTranslation } from 'react-i18next' import { useChain } from '../../hooks/useChain.js' -import { useSwapOnly } from '../../hooks/useSwapOnly.js' import { useToken } from '../../hooks/useToken.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js' @@ -10,7 +9,6 @@ import type { ChainOrderState } from '../../stores/chains/types.js' import type { FormTypeProps } from '../../stores/form/types.js' import { FormKeyHelper } from '../../stores/form/types.js' import { useFieldValues } from '../../stores/form/useFieldValues.js' -import { HiddenUI } from '../../types/widget.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { AvatarBadgedDefault, AvatarBadgedSkeleton } from '../Avatar/Avatar.js' import { TokenAvatar } from '../Avatar/TokenAvatar.js' @@ -23,14 +21,12 @@ import { export const SelectTokenButton: React.FC< FormTypeProps & { - compact: boolean hiddenReverse?: boolean } -> = ({ formType, compact, hiddenReverse }) => { +> = ({ formType, hiddenReverse }) => { const { t } = useTranslation() const navigate = useNavigate() - const { disabledUI, subvariant, hiddenUI } = useWidgetConfig() - const swapOnly = useSwapOnly() + const { disabledUI, subvariant } = useWidgetConfig() const tokenKey = FormKeyHelper.getTokenKey(formType) const [chainId, tokenAddress] = useFieldValues( FormKeyHelper.getChainKey(formType), @@ -56,27 +52,20 @@ export const SelectTokenButton: React.FC< const isSelected = !!(chain && token) const onClick = !disabledUI?.includes(tokenKey) ? handleClick : undefined - const defaultPlaceholder = - formType === 'to' && subvariant === 'refuel' - ? t('main.selectChain') - : (formType === 'to' && swapOnly) || - hiddenUI?.includes(HiddenUI.ChainSelect) - ? t('main.selectToken') - : t('main.selectChainAndToken') + const defaultPlaceholder = `${t('main.select')}...` const cardTitle: string = formType === 'from' && subvariant === 'custom' ? t('header.payWith') : t(`main.${formType}`) return ( - + {cardTitle} {chainId && tokenAddress && (isChainLoading || isTokenLoading) ? ( } title={} subheader={} - compact={compact} /> ) : ( )} diff --git a/packages/widget/src/components/SendToWallet/SendToWallet.style.tsx b/packages/widget/src/components/SendToWallet/SendToWallet.style.tsx deleted file mode 100644 index 895044ad8..000000000 --- a/packages/widget/src/components/SendToWallet/SendToWallet.style.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { cardHeaderClasses, styled } from '@mui/material' -import { CardHeader } from '../Card/CardHeader.js' - -export const SendToWalletCardHeader = styled(CardHeader, { - shouldForwardProp: (prop) => !['selected'].includes(prop as string), -})<{ selected?: boolean }>(({ theme }) => ({ - width: '100%', - [`.${cardHeaderClasses.title}`]: { - color: theme.vars.palette.text.secondary, - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - fontWeight: 500, - width: 254, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 224, - }, - }, - [`.${cardHeaderClasses.subheader}`]: { - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - overflow: 'hidden', - width: 254, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 224, - }, - }, - [`.${cardHeaderClasses.action}`]: { - marginRight: 0, - }, - [`.${cardHeaderClasses.action} > button`]: { - fontSize: 16, - }, - variants: [ - { - props: ({ selected }) => selected, - style: { - [`.${cardHeaderClasses.title}`]: { - color: theme.vars.palette.text.primary, - fontWeight: 600, - width: 224, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 192, - }, - }, - [`.${cardHeaderClasses.subheader}`]: { - width: 224, - [theme.breakpoints.down(theme.breakpoints.values.sm)]: { - width: 192, - }, - }, - }, - }, - ], -})) diff --git a/packages/widget/src/components/SendToWallet/SendToWallet.tsx b/packages/widget/src/components/SendToWallet/SendToWallet.tsx new file mode 100644 index 000000000..fd5ed5d0a --- /dev/null +++ b/packages/widget/src/components/SendToWallet/SendToWallet.tsx @@ -0,0 +1,32 @@ +import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' +import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js' +import { useFieldValues } from '../../stores/form/useFieldValues.js' +import { DisabledUI, HiddenUI } from '../../types/widget.js' +import { SendToWalletButton } from './SendToWalletButton.js' + +export const SendToWallet = () => { + const { disabledUI, hiddenUI } = useWidgetConfig() + const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) + const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) + const [toAddressValue, toChainId, toTokenAddress] = useFieldValues( + 'toAddress', + 'toChain', + 'toToken' + ) + const isAllNetworks = useChainOrderStore((state) => state[`toIsAllNetworks`]) + + const showWalletButton = + !hiddenToAddress && !(disabledToAddress && !toAddressValue) + + const chaindId = toTokenAddress + ? toChainId + : isAllNetworks + ? undefined + : toChainId + + if (!showWalletButton || !chaindId) { + return null + } + + return +} diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx index b1c168c36..3d7aef9cc 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx @@ -1,172 +1,109 @@ -import { useAccount } from '@lifi/wallet-management' -import { useChainTypeFromAddress } from '@lifi/widget-provider' -import CloseRounded from '@mui/icons-material/CloseRounded' -import { Box, Collapse } from '@mui/material' +import Close from '@mui/icons-material/Close' +// import Wallet from '@mui/icons-material/Wallet' +// import EmergencyIcon from '@mui/icons-material/Emergency'; +import { Box, IconButton, Typography } from '@mui/material' import { useNavigate } from '@tanstack/react-router' -import { type MouseEventHandler, useEffect, useRef } from 'react' +import type { MouseEvent } from 'react' import { useTranslation } from 'react-i18next' -import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' +import { useChain } from '../../hooks/useChain.js' +// import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' -import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { useFieldValues } from '../../stores/form/useFieldValues.js' -import { useSendToWalletStore } from '../../stores/settings/useSendToWalletStore.js' -import { DisabledUI, HiddenUI } from '../../types/widget.js' -import { defaultChainIdsByType } from '../../utils/chainType.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { shortenAddress } from '../../utils/wallet.js' -import { AccountAvatar } from '../Avatar/AccountAvatar.js' -import type { CardProps } from '../Card/Card.js' -import { Card } from '../Card/Card.js' -import { CardIconButton } from '../Card/CardIconButton.js' -import { CardTitle } from '../Card/CardTitle.js' -import { SendToWalletCardHeader } from './SendToWallet.style.js' +import { ChainBadgeContent } from '../Avatar/ChainBadgeContent.js' +import { ButtonChip } from '../ButtonChip/ButtonChip.js' -export const SendToWalletButton: React.FC = (props) => { +interface SendToWalletButtonProps { + chainId: number + readOnly?: boolean +} + +// TODO: agree on "required" styling and bookmarks +export const SendToWalletButton: React.FC = ({ + chainId, + readOnly, +}) => { const { t } = useTranslation() const navigate = useNavigate() - const { - disabledUI, - hiddenUI, - toAddress, - toAddresses, - subvariant, - subvariantOptions, - } = useWidgetConfig() - const { showSendToWallet } = useSendToWalletStore((state) => state) - const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues( - 'toAddress', - 'toChain', - 'toToken' - ) + const { subvariant, subvariantOptions, toAddresses } = useWidgetConfig() const { setFieldValue } = useFieldActions() - const { selectedBookmark } = useBookmarks() - const { setSelectedBookmark } = useBookmarkActions() - const { accounts } = useAccount() - const { requiredToAddress } = useToAddressRequirements() - const { getChainTypeFromAddress } = useChainTypeFromAddress() - const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) - const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) - - const address = toAddressFieldValue - ? shortenAddress(toAddressFieldValue) - : t('sendToWallet.enterAddress', { - context: 'short', - }) - - const matchingConnectedAccount = accounts.find( - (account) => account.address === toAddressFieldValue - ) - - const chainType = !matchingConnectedAccount - ? selectedBookmark?.chainType || - (toAddressFieldValue - ? getChainTypeFromAddress(toAddressFieldValue) - : undefined) - : undefined - - const chainId = - toChainId && toTokenAddress - ? toChainId - : matchingConnectedAccount - ? matchingConnectedAccount.chainId - : chainType - ? defaultChainIdsByType[chainType] - : undefined + const [toAddressValue] = useFieldValues('toAddress') + const { chain } = useChain(chainId) - const isConnectedAccount = - selectedBookmark?.isConnectedAccount && - matchingConnectedAccount?.isConnected - const connectedAccountName = matchingConnectedAccount?.connector?.name - const bookmarkName = selectedBookmark?.name - - const headerTitle = isConnectedAccount - ? connectedAccountName || address - : bookmarkName || connectedAccountName || address - - const headerSubheader = - isConnectedAccount || bookmarkName || connectedAccountName ? address : null + const { setSelectedBookmark } = useBookmarkActions() + // const { requiredToAddress } = useToAddressRequirements() - const disabledForChanges = Boolean(toAddressFieldValue) && disabledToAddress + const label = + subvariant === 'custom' && subvariantOptions?.custom === 'deposit' + ? t('header.depositTo') + : t('header.sendToWallet') - const handleOnClick = () => { - navigate({ - to: toAddresses?.length - ? navigationRoutes.configuredWallets - : navigationRoutes.sendToWallet, - }) - } + const handleClick = readOnly + ? undefined + : () => + navigate({ + to: toAddresses?.length + ? navigationRoutes.configuredWallets + : navigationRoutes.sendToWallet, + }) - const clearSelectedBookmark: MouseEventHandler = (e) => { + const handleRemove = (e: MouseEvent) => { e.stopPropagation() setFieldValue('toAddress', '', { isTouched: true }) setSelectedBookmark() } - // The collapse opens instantly on first page load/component mount when there is an address to display - // After which it needs an animated transition for open and closing. - // collapseTransitionTime is used specify the transition time for opening and closing - const collapseTransitionTime = useRef(0) - - // Timeout is needed here to push the collapseTransitionTime update to the back of the event loop so that it doesn't fired too quickly - useEffect(() => { - const timeout = setTimeout(() => { - collapseTransitionTime.current = 225 - }, 0) - return () => clearTimeout(timeout) - }, []) - - const isOpenCollapse = - !hiddenToAddress && (requiredToAddress || showSendToWallet) - - const title = - subvariant === 'custom' && subvariantOptions?.custom === 'deposit' - ? t('header.depositTo') - : t('header.sendToWallet') - return ( - - + ({ + display: 'flex', + alignItems: 'center', + borderRadius: theme.shape.borderRadius, + mt: 1.5, + height: 24, + pl: 0.5, + pr: 1, + })} > - {title} - - - } - title={headerTitle} - subheader={headerSubheader} - selected={!!toAddressFieldValue || disabledToAddress} - action={ - !!toAddressFieldValue && !disabledForChanges ? ( - - - - ) : null - } - /> + + + + {toAddressValue ? shortenAddress(toAddressValue) : label} + - - + {toAddressValue && !readOnly ? ( + + + + ) : null} + {/* ) : } */} + + {/* {requiredToAddress && !toAddressValue && ( + ({ + position: 'absolute', + top: 12, + right: 0, + width: 8, + height: 8, + borderRadius: '50%', + backgroundColor: theme.vars.palette.error.main, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + pointerEvents: 'none', + })} + /> + )} */} + ) } diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx deleted file mode 100644 index effb0d6dd..000000000 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx +++ /dev/null @@ -1,63 +0,0 @@ -import Wallet from '@mui/icons-material/Wallet' -import { Button, Tooltip } from '@mui/material' -import { useTranslation } from 'react-i18next' -import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' -import { useWidgetEvents } from '../../hooks/useWidgetEvents.js' -import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' -import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' -import { useFieldActions } from '../../stores/form/useFieldActions.js' -import { useFieldValues } from '../../stores/form/useFieldValues.js' -import { - sendToWalletStore, - useSendToWalletStore, -} from '../../stores/settings/useSendToWalletStore.js' -import { WidgetEvent } from '../../types/events.js' -import { DisabledUI, HiddenUI } from '../../types/widget.js' - -export const SendToWalletExpandButton: React.FC = () => { - const { t } = useTranslation() - const { disabledUI, hiddenUI } = useWidgetConfig() - const { setFieldValue } = useFieldActions() - const { setSelectedBookmark } = useBookmarkActions() - const emitter = useWidgetEvents() - const { showSendToWallet, setSendToWallet } = useSendToWalletStore( - (state) => state - ) - const [toAddressFieldValue] = useFieldValues('toAddress') - const { requiredToAddress } = useToAddressRequirements() - - if (requiredToAddress || hiddenUI?.includes(HiddenUI.ToAddress)) { - return null - } - - const handleClick = () => { - if (showSendToWallet && !disabledUI?.includes(DisabledUI.ToAddress)) { - setFieldValue('toAddress', '', { isTouched: true }) - setSelectedBookmark() - } - setSendToWallet(!showSendToWallet) - emitter.emit( - WidgetEvent.SendToWalletToggled, - sendToWalletStore.getState().showSendToWallet - ) - } - - const buttonVariant = - showSendToWallet || Boolean(toAddressFieldValue) ? 'contained' : 'text' - - return ( - - - - ) -} diff --git a/packages/widget/src/hooks/useToAddressAutoPopulate.ts b/packages/widget/src/hooks/useToAddressAutoPopulate.ts index 24bd48ca5..26172309b 100644 --- a/packages/widget/src/hooks/useToAddressAutoPopulate.ts +++ b/packages/widget/src/hooks/useToAddressAutoPopulate.ts @@ -4,7 +4,6 @@ import { useCallback } from 'react' import { useBookmarkActions } from '../stores/bookmarks/useBookmarkActions.js' import type { FormType } from '../stores/form/types.js' import { useFieldActions } from '../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../stores/settings/useSendToWalletStore.js' import { useAvailableChains } from './useAvailableChains.js' type UpdateToAddressArgs = { @@ -20,7 +19,6 @@ type UpdateToAddressArgs = { */ export const useToAddressAutoPopulate = () => { const { setFieldValue } = useFieldActions() - const { setSendToWallet } = useSendToWalletActions() const { setSelectedBookmark } = useBookmarkActions() const { getChainById } = useAvailableChains() const { accounts } = useAccount() @@ -81,7 +79,6 @@ export const useToAddressAutoPopulate = () => { chainType: destinationAccount.chainType, isConnectedAccount: true, }) - setSendToWallet(true) return destinationAccount.address } }, @@ -90,7 +87,6 @@ export const useToAddressAutoPopulate = () => { getChainById, setFieldValue, setSelectedBookmark, - setSendToWallet, getChainTypeFromAddress, ] ) diff --git a/packages/widget/src/hooks/useToAddressReset.ts b/packages/widget/src/hooks/useToAddressReset.ts index 32ac94974..76b484992 100644 --- a/packages/widget/src/hooks/useToAddressReset.ts +++ b/packages/widget/src/hooks/useToAddressReset.ts @@ -4,15 +4,13 @@ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js' import { useBookmarkActions } from '../stores/bookmarks/useBookmarkActions.js' import { useBookmarks } from '../stores/bookmarks/useBookmarks.js' import { useFieldActions } from '../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../stores/settings/useSendToWalletStore.js' import { RequiredUI } from '../types/widget.js' export const useToAddressReset = () => { const { requiredUI } = useWidgetConfig() - const { setFieldValue, isDirty } = useFieldActions() + const { setFieldValue } = useFieldActions() const { selectedBookmark } = useBookmarks() const { setSelectedBookmark } = useBookmarkActions() - const { setSendToWallet } = useSendToWalletActions() const tryResetToAddress = useCallback( (toChain: ExtendedChain) => { @@ -24,30 +22,14 @@ export const useToAddressReset = () => { const shouldResetToAddress = !requiredToAddress && !bookmarkSatisfiesToChainType - // The toAddress field is required and always visible when bridging between - // different ecosystems (fromChain and toChain have different chain types). // We reset toAddress on each chain change if it's no longer required, ensuring that - // switching chain types doesn't leave a previously set toAddress value when - // the "Send to Wallet" field is hidden. + // switching chain types doesn't leave a stale toAddress from a different ecosystem. if (shouldResetToAddress) { setFieldValue('toAddress', '', { isTouched: true }) setSelectedBookmark() - // If toAddress was auto-filled (e.g., when making cross-ecosystem bridging and compatible destination wallet was connected) - // and not manually edited by the user, we need to hide "Send to Wallet". - const isToAddressDirty = isDirty('toAddress') - if (!isToAddressDirty) { - setSendToWallet(false) - } } }, - [ - setFieldValue, - isDirty, - setSelectedBookmark, - setSendToWallet, - requiredUI, - selectedBookmark, - ] + [setFieldValue, setSelectedBookmark, requiredUI, selectedBookmark] ) return { diff --git a/packages/widget/src/i18n/en.json b/packages/widget/src/i18n/en.json index 1f988bee4..ae62f63f5 100644 --- a/packages/widget/src/i18n/en.json +++ b/packages/widget/src/i18n/en.json @@ -286,9 +286,7 @@ "rateChange": "Rate change", "receiving": "Receiving", "refuelStepDetails": "Get gas via {{tool}}", - "selectChain": "Select chain", - "selectChainAndToken": "Select chain and token", - "selectToken": "Select token", + "select": "Select", "sendToAddress": "Send to {{address}}", "sendToWallet": "Send to a different wallet", "sending": "Sending", diff --git a/packages/widget/src/pages/MainPage/MainPage.tsx b/packages/widget/src/pages/MainPage/MainPage.tsx index 95201d9e8..17fad0758 100644 --- a/packages/widget/src/pages/MainPage/MainPage.tsx +++ b/packages/widget/src/pages/MainPage/MainPage.tsx @@ -8,8 +8,6 @@ import { PageContainer } from '../../components/PageContainer.js' import { PoweredBy } from '../../components/PoweredBy/PoweredBy.js' import { Routes } from '../../components/Routes/Routes.js' import { SelectChainAndToken } from '../../components/SelectChainAndToken.js' -import { SendToWalletButton } from '../../components/SendToWallet/SendToWalletButton.js' -import { SendToWalletExpandButton } from '../../components/SendToWallet/SendToWalletExpandButton.js' import { useHeader } from '../../hooks/useHeader.js' import { useWideVariant } from '../../hooks/useWideVariant.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' @@ -43,31 +41,28 @@ export const MainPage: React.FC = () => { useHeader(title) - const marginSx = { marginBottom: 2 } - return ( - - {custom ? ( - {contractComponent} - ) : null} - - {!custom || subvariantOptions?.custom === 'deposit' ? ( - - ) : null} - {!wideVariant ? : null} - - {showGasRefuelMessage ? : null} - + + {custom ? ( + {contractComponent} + ) : null} + + {!custom || subvariantOptions?.custom === 'deposit' ? ( + + ) : null} + {!wideVariant ? : null} + {showGasRefuelMessage ? : null} + - {showPoweredBy ? : null} diff --git a/packages/widget/src/pages/SendToWallet/BookmarksPage.tsx b/packages/widget/src/pages/SendToWallet/BookmarksPage.tsx index c3d391685..07c3d824a 100644 --- a/packages/widget/src/pages/SendToWallet/BookmarksPage.tsx +++ b/packages/widget/src/pages/SendToWallet/BookmarksPage.tsx @@ -20,7 +20,6 @@ import type { Bookmark } from '../../stores/bookmarks/types.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import { defaultChainIdsByType } from '../../utils/chainType.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { shortenAddress } from '../../utils/wallet.js' @@ -43,7 +42,6 @@ export const BookmarksPage = () => { useBookmarkActions() const navigate = useNavigate() const { setFieldValue } = useFieldActions() - const { setSendToWallet } = useSendToWalletActions() const { variant } = useWidgetConfig() const { getAddressLink } = useExplorer() @@ -59,7 +57,6 @@ export const BookmarksPage = () => { isDirty: true, }) setSelectedBookmark(bookmark) - setSendToWallet(true) navigate({ to: navigationRoutes.home, replace: true }) } diff --git a/packages/widget/src/pages/SendToWallet/ConfirmAddressSheet.tsx b/packages/widget/src/pages/SendToWallet/ConfirmAddressSheet.tsx index 707fdc145..65a76277a 100644 --- a/packages/widget/src/pages/SendToWallet/ConfirmAddressSheet.tsx +++ b/packages/widget/src/pages/SendToWallet/ConfirmAddressSheet.tsx @@ -11,7 +11,6 @@ import { useNavigateBack } from '../../hooks/useNavigateBack.js' import { useSetContentHeight } from '../../hooks/useSetContentHeight.js' import type { Bookmark } from '../../stores/bookmarks/types.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import { IconContainer, SendToWalletButtonRow, @@ -52,8 +51,6 @@ const ConfirmAddressSheetContent: React.FC = ({ const { t } = useTranslation() const navigateBack = useNavigateBack() const { setFieldValue } = useFieldActions() - const { setSendToWallet } = useSendToWalletActions() - const containerRef = useRef(null) useSetContentHeight(containerRef) @@ -64,7 +61,6 @@ const ConfirmAddressSheetContent: React.FC = ({ isDirty: true, }) onConfirm?.(validatedBookmark) - setSendToWallet(true) onClose() navigateBack() } diff --git a/packages/widget/src/pages/SendToWallet/ConnectedWalletsPage.tsx b/packages/widget/src/pages/SendToWallet/ConnectedWalletsPage.tsx index 584fb9b5a..a0ae57246 100644 --- a/packages/widget/src/pages/SendToWallet/ConnectedWalletsPage.tsx +++ b/packages/widget/src/pages/SendToWallet/ConnectedWalletsPage.tsx @@ -17,7 +17,6 @@ import { useHeader } from '../../hooks/useHeader.js' import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { shortenAddress } from '../../utils/wallet.js' import { EmptyListIndicator } from './EmptyListIndicator.js' @@ -35,7 +34,6 @@ export const ConnectedWalletsPage = () => { const { requiredToChainType } = useToAddressRequirements() const navigate = useNavigate() const { setFieldValue } = useFieldActions() - const { setSendToWallet } = useSendToWalletActions() const [moreMenuAnchorEl, setMenuAnchorEl] = useState() const moreMenuId = useId() const open = Boolean(moreMenuAnchorEl) @@ -54,7 +52,6 @@ export const ConnectedWalletsPage = () => { chainType: account.chainType!, isConnectedAccount: true, }) - setSendToWallet(true) navigate({ to: navigationRoutes.home, replace: true, diff --git a/packages/widget/src/pages/SendToWallet/RecentWalletsPage.tsx b/packages/widget/src/pages/SendToWallet/RecentWalletsPage.tsx index cff25ae09..0688ca3f1 100644 --- a/packages/widget/src/pages/SendToWallet/RecentWalletsPage.tsx +++ b/packages/widget/src/pages/SendToWallet/RecentWalletsPage.tsx @@ -20,7 +20,6 @@ import type { Bookmark } from '../../stores/bookmarks/types.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import { defaultChainIdsByType } from '../../utils/chainType.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { shortenAddress } from '../../utils/wallet.js' @@ -46,7 +45,6 @@ export const RecentWalletsPage = () => { addRecentWallet, } = useBookmarkActions() const { setFieldValue } = useFieldActions() - const { setSendToWallet } = useSendToWalletActions() const moreMenuId = useId() const [moreMenuAnchorEl, setMenuAnchorEl] = useState() const open = Boolean(moreMenuAnchorEl) @@ -61,7 +59,6 @@ export const RecentWalletsPage = () => { isDirty: true, }) setSelectedBookmark(recentWallet) - setSendToWallet(true) navigate({ to: navigationRoutes.home, replace: true, diff --git a/packages/widget/src/stores/form/FormUpdater.tsx b/packages/widget/src/stores/form/FormUpdater.tsx index a7f83ccfb..b4ea32b77 100644 --- a/packages/widget/src/stores/form/FormUpdater.tsx +++ b/packages/widget/src/stores/form/FormUpdater.tsx @@ -3,7 +3,6 @@ import { useEffect } from 'react' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' import { formDefaultValues } from '../../stores/form/createFormStore.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import type { DefaultValues } from './types.js' import { useFieldActions } from './useFieldActions.js' @@ -12,7 +11,6 @@ export const FormUpdater: React.FC<{ }> = ({ reactiveFormValues }) => { const { toAddress } = useWidgetConfig() const { account } = useAccount() - const { setSendToWallet } = useSendToWalletActions() const { setSelectedBookmark } = useBookmarkActions() const { setUserAndDefaultValues } = useFieldActions() @@ -20,9 +18,6 @@ export const FormUpdater: React.FC<{ // Includes special logic for chain fields, where account.chainId is only a fallback and not a direct reactivity source. // biome-ignore lint/correctness/useExhaustiveDependencies: account.chainId is used as a fallback only and does not need to be a dependency for reactivity. useEffect(() => { - if (reactiveFormValues.toAddress) { - setSendToWallet(true) - } if (toAddress) { setSelectedBookmark(toAddress) } @@ -34,7 +29,6 @@ export const FormUpdater: React.FC<{ toAddress, reactiveFormValues, setUserAndDefaultValues, - setSendToWallet, setSelectedBookmark, ]) diff --git a/packages/widget/src/stores/form/URLSearchParamsBuilder.tsx b/packages/widget/src/stores/form/URLSearchParamsBuilder.tsx index 69cdefc7a..fe927c3ce 100644 --- a/packages/widget/src/stores/form/URLSearchParamsBuilder.tsx +++ b/packages/widget/src/stores/form/URLSearchParamsBuilder.tsx @@ -2,7 +2,6 @@ import { useLocation } from '@tanstack/react-router' import { useEffect } from 'react' import { useAddressValidation } from '../../hooks/useAddressValidation.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import { useBookmarkActions } from '../bookmarks/useBookmarkActions.js' import type { FormFieldNames } from '../form/types.js' import { useFieldActions } from '../form/useFieldActions.js' @@ -23,7 +22,6 @@ export const URLSearchParamsBuilder = () => { const { pathname } = useLocation() const touchedFields = useTouchedFields() const values = useFieldValues(...formValueKeys) - const { setSendToWallet } = useSendToWalletActions() const { setSelectedBookmark, addRecentWallet } = useBookmarkActions() const { validateAddress } = useAddressValidation() const { buildUrl } = useWidgetConfig() @@ -58,7 +56,6 @@ export const URLSearchParamsBuilder = () => { setUserAndDefaultValues({ toAddress }) setSelectedBookmark(bookmark) addRecentWallet(bookmark) - setSendToWallet(true) } } catch (_) { // Address validation failed @@ -70,7 +67,6 @@ export const URLSearchParamsBuilder = () => { initializeFromAddress() }, [ setUserAndDefaultValues, - setSendToWallet, validateAddress, setSelectedBookmark, addRecentWallet, diff --git a/packages/widget/src/stores/form/useFormRef.ts b/packages/widget/src/stores/form/useFormRef.ts index a751aa84f..2c812df30 100644 --- a/packages/widget/src/stores/form/useFormRef.ts +++ b/packages/widget/src/stores/form/useFormRef.ts @@ -1,12 +1,10 @@ import { useImperativeHandle } from 'react' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' import { formDefaultValues } from '../../stores/form/createFormStore.js' -import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js' import type { FormRef } from '../../types/widget.js' import type { FormStoreStore, GenericFormValue } from './types.js' export const useFormRef = (formStore: FormStoreStore, formRef?: FormRef) => { - const { setSendToWallet } = useSendToWalletActions() const { setSelectedBookmark } = useBookmarkActions() useImperativeHandle(formRef, () => { @@ -26,15 +24,6 @@ export const useFormRef = (formStore: FormStoreStore, formRef?: FormRef) => { (isToAddressObj ? value?.address : value) || formDefaultValues.toAddress - // sets the send to wallet button state to be open - // if there is an address to display - if (address) { - setSendToWallet(address) - } - - // we can assume that the toAddress has been passed as ToAddress object - // and display it accordingly - this ensures that if a name is included - // that it is displayed in the Send To Wallet form field correctly if (isToAddressObj) { setSelectedBookmark(value) } @@ -58,5 +47,5 @@ export const useFormRef = (formStore: FormStoreStore, formRef?: FormRef) => { .setFieldValue(fieldName, sanitizedValue, fieldValueOptions) }, } - }, [formStore, setSendToWallet, setSelectedBookmark]) + }, [formStore, setSelectedBookmark]) } diff --git a/packages/widget/src/stores/settings/types.ts b/packages/widget/src/stores/settings/types.ts index 8726b88fb..a9f4886a1 100644 --- a/packages/widget/src/stores/settings/types.ts +++ b/packages/widget/src/stores/settings/types.ts @@ -48,14 +48,6 @@ export interface SettingsActions { export type SettingsState = SettingsProps & SettingsActions -interface SendToWalletState { - showSendToWallet: boolean -} - -export interface SendToWalletStore extends SendToWalletState { - setSendToWallet(value: boolean): void -} - export interface SplitSubvariantState { state?: SplitSubvariant setState(state: SplitSubvariant): void diff --git a/packages/widget/src/stores/settings/useSendToWalletStore.ts b/packages/widget/src/stores/settings/useSendToWalletStore.ts deleted file mode 100644 index a790dbf47..000000000 --- a/packages/widget/src/stores/settings/useSendToWalletStore.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { create } from 'zustand' -import { useShallow } from 'zustand/shallow' -import type { SendToWalletStore } from './types.js' - -export const sendToWalletStore = create((set) => ({ - showSendToWallet: false, - setSendToWallet: (value) => - set({ - showSendToWallet: value, - }), -})) - -export const useSendToWalletStore = ( - selector: (state: SendToWalletStore) => T -): T => { - return sendToWalletStore(useShallow(selector)) -} - -export const useSendToWalletActions = () => { - const actions = useSendToWalletStore((store) => ({ - setSendToWallet: store.setSendToWallet, - })) - - return actions -} From 7097753f97b9a9f81c68d19777038910d4dd2834 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Tue, 24 Mar 2026 17:27:01 +0000 Subject: [PATCH 2/8] feat: revert send to wallet card --- .../components/AmountInput/AmountInput.tsx | 4 +- .../components/SendToWallet/SendToWallet.tsx | 32 --- .../SendToWallet/SendToWalletButton.style.tsx | 55 +++++ .../SendToWallet/SendToWalletButton.tsx | 229 +++++++++++------- .../SendToWalletExpandButton.style.ts | 43 ++++ .../SendToWallet/SendToWalletExpandButton.tsx | 56 +++++ .../widget/src/pages/MainPage/MainPage.tsx | 2 + 7 files changed, 304 insertions(+), 117 deletions(-) delete mode 100644 packages/widget/src/components/SendToWallet/SendToWallet.tsx create mode 100644 packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx create mode 100644 packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts create mode 100644 packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx diff --git a/packages/widget/src/components/AmountInput/AmountInput.tsx b/packages/widget/src/components/AmountInput/AmountInput.tsx index f8bf82721..5bfe5ed9c 100644 --- a/packages/widget/src/components/AmountInput/AmountInput.tsx +++ b/packages/widget/src/components/AmountInput/AmountInput.tsx @@ -18,7 +18,7 @@ import { } from '../../utils/format.js' import { fitInputText } from '../../utils/input.js' import { InputCard } from '../Card/InputCard.js' -import { SendToWallet } from '../SendToWallet/SendToWallet.js' +import { SendToWalletExpandButton } from '../SendToWallet/SendToWalletExpandButton.js' import { AmountInputCardHeader, AmountInputCardTitle, @@ -47,7 +47,7 @@ export const AmountInput: React.FC = ({ formType }) => { } + endAdornment={} bottomAdornment={} disabled={disabled} /> diff --git a/packages/widget/src/components/SendToWallet/SendToWallet.tsx b/packages/widget/src/components/SendToWallet/SendToWallet.tsx deleted file mode 100644 index fd5ed5d0a..000000000 --- a/packages/widget/src/components/SendToWallet/SendToWallet.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' -import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js' -import { useFieldValues } from '../../stores/form/useFieldValues.js' -import { DisabledUI, HiddenUI } from '../../types/widget.js' -import { SendToWalletButton } from './SendToWalletButton.js' - -export const SendToWallet = () => { - const { disabledUI, hiddenUI } = useWidgetConfig() - const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) - const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) - const [toAddressValue, toChainId, toTokenAddress] = useFieldValues( - 'toAddress', - 'toChain', - 'toToken' - ) - const isAllNetworks = useChainOrderStore((state) => state[`toIsAllNetworks`]) - - const showWalletButton = - !hiddenToAddress && !(disabledToAddress && !toAddressValue) - - const chaindId = toTokenAddress - ? toChainId - : isAllNetworks - ? undefined - : toChainId - - if (!showWalletButton || !chaindId) { - return null - } - - return -} diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx new file mode 100644 index 000000000..895044ad8 --- /dev/null +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx @@ -0,0 +1,55 @@ +import { cardHeaderClasses, styled } from '@mui/material' +import { CardHeader } from '../Card/CardHeader.js' + +export const SendToWalletCardHeader = styled(CardHeader, { + shouldForwardProp: (prop) => !['selected'].includes(prop as string), +})<{ selected?: boolean }>(({ theme }) => ({ + width: '100%', + [`.${cardHeaderClasses.title}`]: { + color: theme.vars.palette.text.secondary, + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + fontWeight: 500, + width: 254, + [theme.breakpoints.down(theme.breakpoints.values.sm)]: { + width: 224, + }, + }, + [`.${cardHeaderClasses.subheader}`]: { + textOverflow: 'ellipsis', + whiteSpace: 'nowrap', + overflow: 'hidden', + width: 254, + [theme.breakpoints.down(theme.breakpoints.values.sm)]: { + width: 224, + }, + }, + [`.${cardHeaderClasses.action}`]: { + marginRight: 0, + }, + [`.${cardHeaderClasses.action} > button`]: { + fontSize: 16, + }, + variants: [ + { + props: ({ selected }) => selected, + style: { + [`.${cardHeaderClasses.title}`]: { + color: theme.vars.palette.text.primary, + fontWeight: 600, + width: 224, + [theme.breakpoints.down(theme.breakpoints.values.sm)]: { + width: 192, + }, + }, + [`.${cardHeaderClasses.subheader}`]: { + width: 224, + [theme.breakpoints.down(theme.breakpoints.values.sm)]: { + width: 192, + }, + }, + }, + }, + ], +})) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx index 3d7aef9cc..322bbacc6 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx @@ -1,109 +1,172 @@ -import Close from '@mui/icons-material/Close' -// import Wallet from '@mui/icons-material/Wallet' -// import EmergencyIcon from '@mui/icons-material/Emergency'; -import { Box, IconButton, Typography } from '@mui/material' +import { useAccount } from '@lifi/wallet-management' +import { useChainTypeFromAddress } from '@lifi/widget-provider' +import CloseRounded from '@mui/icons-material/CloseRounded' +import { Box, Collapse } from '@mui/material' import { useNavigate } from '@tanstack/react-router' -import type { MouseEvent } from 'react' +import { type MouseEventHandler, useEffect, useRef } from 'react' import { useTranslation } from 'react-i18next' -import { useChain } from '../../hooks/useChain.js' -// import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' +import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js' +import { useBookmarks } from '../../stores/bookmarks/useBookmarks.js' import { useFieldActions } from '../../stores/form/useFieldActions.js' import { useFieldValues } from '../../stores/form/useFieldValues.js' +import { DisabledUI, HiddenUI } from '../../types/widget.js' +import { defaultChainIdsByType } from '../../utils/chainType.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { shortenAddress } from '../../utils/wallet.js' -import { ChainBadgeContent } from '../Avatar/ChainBadgeContent.js' -import { ButtonChip } from '../ButtonChip/ButtonChip.js' +import { AccountAvatar } from '../Avatar/AccountAvatar.js' +import type { CardProps } from '../Card/Card.js' +import { Card } from '../Card/Card.js' +import { CardIconButton } from '../Card/CardIconButton.js' +import { CardTitle } from '../Card/CardTitle.js' +import { SendToWalletCardHeader } from './SendToWalletButton.style.js' -interface SendToWalletButtonProps { - chainId: number - readOnly?: boolean -} - -// TODO: agree on "required" styling and bookmarks -export const SendToWalletButton: React.FC = ({ - chainId, - readOnly, -}) => { +export const SendToWalletButton: React.FC = (props) => { const { t } = useTranslation() const navigate = useNavigate() - const { subvariant, subvariantOptions, toAddresses } = useWidgetConfig() + const { + disabledUI, + hiddenUI, + toAddress, + toAddresses, + subvariant, + subvariantOptions, + } = useWidgetConfig() + const [toAddressFieldValue, toChainId, toTokenAddress] = useFieldValues( + 'toAddress', + 'toChain', + 'toToken' + ) const { setFieldValue } = useFieldActions() - const [toAddressValue] = useFieldValues('toAddress') - const { chain } = useChain(chainId) - + const { selectedBookmark } = useBookmarks() const { setSelectedBookmark } = useBookmarkActions() - // const { requiredToAddress } = useToAddressRequirements() + const { accounts } = useAccount() + const { getChainTypeFromAddress } = useChainTypeFromAddress() + const { requiredToAddress } = useToAddressRequirements() + const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) + const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) - const label = - subvariant === 'custom' && subvariantOptions?.custom === 'deposit' - ? t('header.depositTo') - : t('header.sendToWallet') + const address = toAddressFieldValue + ? shortenAddress(toAddressFieldValue) + : t('sendToWallet.enterAddress', { + context: 'short', + }) + + const matchingConnectedAccount = accounts.find( + (account) => account.address === toAddressFieldValue + ) + + const chainType = !matchingConnectedAccount + ? selectedBookmark?.chainType || + (toAddressFieldValue + ? getChainTypeFromAddress(toAddressFieldValue) + : undefined) + : undefined + + const chainId = + toChainId && toTokenAddress + ? toChainId + : matchingConnectedAccount + ? matchingConnectedAccount.chainId + : chainType && chainType in defaultChainIdsByType + ? defaultChainIdsByType[ + chainType as keyof typeof defaultChainIdsByType + ] + : undefined + + const isConnectedAccount = + selectedBookmark?.isConnectedAccount && + matchingConnectedAccount?.isConnected + const connectedAccountName = matchingConnectedAccount?.connector?.name + const bookmarkName = selectedBookmark?.name - const handleClick = readOnly - ? undefined - : () => - navigate({ - to: toAddresses?.length - ? navigationRoutes.configuredWallets - : navigationRoutes.sendToWallet, - }) + const headerTitle = isConnectedAccount + ? connectedAccountName || address + : bookmarkName || connectedAccountName || address - const handleRemove = (e: MouseEvent) => { + const headerSubheader = + isConnectedAccount || bookmarkName || connectedAccountName ? address : null + + const disabledForChanges = Boolean(toAddressFieldValue) && disabledToAddress + + const handleOnClick = () => { + navigate({ + to: toAddresses?.length + ? navigationRoutes.configuredWallets + : navigationRoutes.sendToWallet, + }) + } + + const clearSelectedBookmark: MouseEventHandler = (e) => { e.stopPropagation() setFieldValue('toAddress', '', { isTouched: true }) setSelectedBookmark() } + // The collapse opens instantly on first page load/component mount when there is an address to display + // After which it needs an animated transition for open and closing. + // collapseTransitionTime is used specify the transition time for opening and closing + const collapseTransitionTime = useRef(0) + + // Timeout is needed here to push the collapseTransitionTime update to the back of the event loop so that it doesn't fired too quickly + useEffect(() => { + const timeout = setTimeout(() => { + collapseTransitionTime.current = 225 + }, 0) + return () => clearTimeout(timeout) + }, []) + + const isOpenCollapse = + !hiddenToAddress && (requiredToAddress || !!toAddressFieldValue) + + const title = + subvariant === 'custom' && subvariantOptions?.custom === 'deposit' + ? t('header.depositTo') + : t('header.sendToWallet') + return ( - - ({ - display: 'flex', - alignItems: 'center', - borderRadius: theme.shape.borderRadius, - mt: 1.5, - height: 24, - pl: 0.5, - pr: 1, - })} + + - - - - {toAddressValue ? shortenAddress(toAddressValue) : label} - + {title} + + + } + title={headerTitle} + subheader={headerSubheader} + selected={!!toAddressFieldValue || disabledToAddress} + action={ + !!toAddressFieldValue && !disabledForChanges ? ( + + + + ) : null + } + /> - {toAddressValue && !readOnly ? ( - - - - ) : null} - {/* ) : } */} - - {/* {requiredToAddress && !toAddressValue && ( - ({ - position: 'absolute', - top: 12, - right: 0, - width: 8, - height: 8, - borderRadius: '50%', - backgroundColor: theme.vars.palette.error.main, - display: 'flex', - alignItems: 'center', - justifyContent: 'center', - pointerEvents: 'none', - })} - /> - )} */} - + + ) } diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts new file mode 100644 index 000000000..1f2968ec2 --- /dev/null +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts @@ -0,0 +1,43 @@ +import { Box, styled, Typography } from '@mui/material' +import { ButtonChip } from '../ButtonChip/ButtonChip.js' + +const animationDuration = 225 + +export const SendToWalletExpandButtonIcon = styled(Box)({ + display: 'flex', + alignItems: 'center', +}) + +export const SendToWalletExpandButtonLabel = styled(Typography)({ + fontSize: 12, + fontWeight: 700, + lineHeight: 1.334, +}) + +export const SendToWalletExpandButtonChip = styled(ButtonChip)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + borderRadius: theme.shape.borderRadius, + paddingLeft: theme.spacing(0.75), + paddingRight: theme.spacing(0.75), + marginTop: theme.spacing(1.5), + height: 24, + minWidth: 'auto', + '& .MuiTypography-root': { + maxWidth: 0, + paddingLeft: 0, + paddingRight: 0, + opacity: 0, + overflow: 'hidden', + whiteSpace: 'nowrap', + transform: 'translateX(-4px)', + transition: `max-width ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), padding ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), opacity ${animationDuration / 2}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, + }, + '&:hover .MuiTypography-root': { + maxWidth: 120, + paddingLeft: theme.spacing(0.5), + paddingRight: theme.spacing(0.5), + opacity: 1, + transform: 'translateX(0)', + }, +})) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx new file mode 100644 index 000000000..74cf5aad8 --- /dev/null +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx @@ -0,0 +1,56 @@ +import ChevronRightRounded from '@mui/icons-material/ChevronRightRounded' +import Wallet from '@mui/icons-material/Wallet' +import { useNavigate } from '@tanstack/react-router' +import { useTranslation } from 'react-i18next' +import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' +import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' +import { useFieldValues } from '../../stores/form/useFieldValues.js' +import { DisabledUI, HiddenUI } from '../../types/widget.js' +import { navigationRoutes } from '../../utils/navigationRoutes.js' +import { + SendToWalletExpandButtonChip, + SendToWalletExpandButtonIcon, + SendToWalletExpandButtonLabel, +} from './SendToWalletExpandButton.style.js' + +export const SendToWalletExpandButton = () => { + const { t } = useTranslation() + const navigate = useNavigate() + const { subvariant, subvariantOptions, toAddresses } = useWidgetConfig() + const { disabledUI, hiddenUI } = useWidgetConfig() + const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) + const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) + const { requiredToAddress } = useToAddressRequirements() + const [toAddressValue] = useFieldValues('toAddress') + + if ( + hiddenToAddress || + disabledToAddress || + toAddressValue || + requiredToAddress + ) { + return null + } + + const label = + subvariant === 'custom' && subvariantOptions?.custom === 'deposit' + ? t('header.depositTo') + : t('header.sendToWallet') + + const handleClick = () => + navigate({ + to: toAddresses?.length + ? navigationRoutes.configuredWallets + : navigationRoutes.sendToWallet, + }) + + return ( + + + + {label} + + + + ) +} diff --git a/packages/widget/src/pages/MainPage/MainPage.tsx b/packages/widget/src/pages/MainPage/MainPage.tsx index 17fad0758..7802a7ce6 100644 --- a/packages/widget/src/pages/MainPage/MainPage.tsx +++ b/packages/widget/src/pages/MainPage/MainPage.tsx @@ -8,6 +8,7 @@ import { PageContainer } from '../../components/PageContainer.js' import { PoweredBy } from '../../components/PoweredBy/PoweredBy.js' import { Routes } from '../../components/Routes/Routes.js' import { SelectChainAndToken } from '../../components/SelectChainAndToken.js' +import { SendToWalletButton } from '../../components/SendToWallet/SendToWalletButton.js' import { useHeader } from '../../hooks/useHeader.js' import { useWideVariant } from '../../hooks/useWideVariant.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' @@ -60,6 +61,7 @@ export const MainPage: React.FC = () => { ) : null} {!wideVariant ? : null} + {showGasRefuelMessage ? : null} From 1f83dcd6594c39554890629cd4d56d370302cf03 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Wed, 25 Mar 2026 11:04:48 +0000 Subject: [PATCH 3/8] feat: replace required tag --- .../AmountInput/AmountInput.style.tsx | 6 +- .../AmountInputEndAdornment.style.ts | 10 +++- .../src/components/ButtonChip/ButtonChip.tsx | 10 ---- .../widget/src/components/Card/CardLabel.tsx | 13 +++- .../widget/src/components/Card/CardTitle.tsx | 18 +----- .../Messages/ToAddressRequiredMessage.tsx | 27 --------- .../components/Messages/WarningMessages.tsx | 3 - .../components/Messages/useMessageQueue.ts | 11 +--- .../SendToWallet/SendToWalletButton.style.tsx | 23 +++++++- .../SendToWallet/SendToWalletButton.tsx | 20 ++++++- .../SendToWalletExpandButton.style.ts | 59 ++++++++++--------- packages/widget/src/i18n/en.json | 4 +- 12 files changed, 98 insertions(+), 106 deletions(-) delete mode 100644 packages/widget/src/components/ButtonChip/ButtonChip.tsx delete mode 100644 packages/widget/src/components/Messages/ToAddressRequiredMessage.tsx diff --git a/packages/widget/src/components/AmountInput/AmountInput.style.tsx b/packages/widget/src/components/AmountInput/AmountInput.style.tsx index 3a87a276e..f15ad05c6 100644 --- a/packages/widget/src/components/AmountInput/AmountInput.style.tsx +++ b/packages/widget/src/components/AmountInput/AmountInput.style.tsx @@ -46,13 +46,13 @@ export const Input = styled(InputBase)(({ theme }) => ({ })) export const AmountInputCardTitle = styled(CardTitle)(({ theme }) => ({ - padding: theme.spacing(2, 0, 0, 0), + padding: theme.spacing(0), })) export const AmountInputCardHeader = styled(Box)(({ theme }) => ({ - padding: theme.spacing(0, 2, 0, 2), + padding: theme.spacing(2, 2, 0, 2), display: 'flex', justifyContent: 'space-between', - alignItems: 'start', + alignItems: 'center', height: 30, })) diff --git a/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts index 1842f493c..cac6cddf6 100644 --- a/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts +++ b/packages/widget/src/components/AmountInput/AmountInputEndAdornment.style.ts @@ -1,5 +1,5 @@ import { Box, styled } from '@mui/material' -import { ButtonChip } from '../ButtonChip/ButtonChip.js' +import { ButtonTertiary } from '../ButtonTertiary.js' export const ButtonContainer = styled(Box)(({ theme }) => ({ display: 'flex', @@ -7,6 +7,12 @@ export const ButtonContainer = styled(Box)(({ theme }) => ({ padding: theme.spacing(0, 2, 2, 2), })) -export const AmountInputButton = styled(ButtonChip)(() => ({ +export const AmountInputButton = styled(ButtonTertiary)(({ theme }) => ({ flex: 1, + padding: theme.spacing(0.5, 1.5), + fontSize: 12, + fontWeight: 700, + lineHeight: 1.3334, + height: 'auto', + borderRadius: theme.shape.borderRadiusSecondary, })) diff --git a/packages/widget/src/components/ButtonChip/ButtonChip.tsx b/packages/widget/src/components/ButtonChip/ButtonChip.tsx deleted file mode 100644 index 725e765db..000000000 --- a/packages/widget/src/components/ButtonChip/ButtonChip.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import { styled } from '@mui/material' -import { ButtonTertiary } from '../ButtonTertiary.js' - -export const ButtonChip = styled(ButtonTertiary)(({ theme }) => ({ - padding: theme.spacing(0.5, 1.5), - fontSize: 12, - fontWeight: 700, - lineHeight: 1.3334, - height: 'auto', -})) diff --git a/packages/widget/src/components/Card/CardLabel.tsx b/packages/widget/src/components/Card/CardLabel.tsx index c59053785..9156a5697 100644 --- a/packages/widget/src/components/Card/CardLabel.tsx +++ b/packages/widget/src/components/Card/CardLabel.tsx @@ -2,7 +2,7 @@ import { Box, styled, Typography } from '@mui/material' export const CardLabel = styled(Box, { shouldForwardProp: (prop) => prop !== 'variant', -})<{ variant?: 'secondary' | 'success' }>(({ theme }) => ({ +})<{ variant?: 'secondary' | 'success' | 'warning' }>(({ theme }) => ({ borderRadius: theme.vars.shape.borderRadius, padding: 0, display: 'flex', @@ -39,6 +39,17 @@ export const CardLabel = styled(Box, { }), }, }, + { + props: { variant: 'warning' }, + style: { + backgroundColor: `rgba(${theme.vars.palette.warning.mainChannel} / 0.32)`, + color: `color-mix(in srgb, ${theme.vars.palette.warning.main} 64%, black)`, + ...theme.applyStyles('dark', { + backgroundColor: `rgba(${theme.vars.palette.warning.mainChannel} / 0.16)`, + color: theme.vars.palette.warning.main, + }), + }, + }, ], })) diff --git a/packages/widget/src/components/Card/CardTitle.tsx b/packages/widget/src/components/Card/CardTitle.tsx index f0c3019bb..4cfa21e1d 100644 --- a/packages/widget/src/components/Card/CardTitle.tsx +++ b/packages/widget/src/components/Card/CardTitle.tsx @@ -1,26 +1,10 @@ import { styled, Typography } from '@mui/material' -export const CardTitle = styled(Typography, { - shouldForwardProp: (prop) => !['required'].includes(prop as string), -})<{ required?: boolean }>(({ theme }) => ({ +export const CardTitle = styled(Typography)(({ theme }) => ({ fontSize: 14, lineHeight: 1, fontWeight: 700, padding: theme.spacing(2, 2, 0, 2), textAlign: 'left', color: theme.vars.palette.text.primary, - '&:after': { - content: 'none', - color: theme.vars.palette.error.main, - }, - variants: [ - { - props: ({ required }) => required, - style: { - '&:after': { - content: '" *"', - }, - }, - }, - ], })) diff --git a/packages/widget/src/components/Messages/ToAddressRequiredMessage.tsx b/packages/widget/src/components/Messages/ToAddressRequiredMessage.tsx deleted file mode 100644 index 0e3357d22..000000000 --- a/packages/widget/src/components/Messages/ToAddressRequiredMessage.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import Wallet from '@mui/icons-material/Wallet' -import type { BoxProps } from '@mui/material' -import { Typography } from '@mui/material' -import { useTranslation } from 'react-i18next' -import { AlertMessage } from './AlertMessage.js' - -export const ToAddressRequiredMessage: React.FC = ({ ...props }) => { - const { t } = useTranslation() - return ( - - {t('info.message.toAddressIsRequired')} - - } - icon={} - multiline - {...props} - /> - ) -} diff --git a/packages/widget/src/components/Messages/WarningMessages.tsx b/packages/widget/src/components/Messages/WarningMessages.tsx index e7deb2c42..bb78b781e 100644 --- a/packages/widget/src/components/Messages/WarningMessages.tsx +++ b/packages/widget/src/components/Messages/WarningMessages.tsx @@ -7,7 +7,6 @@ import { FundsSufficiencyMessage } from './FundsSufficiencyMessage.js' import { GasSufficiencyMessage } from './GasSufficiencyMessage.js' import { MinFromAmountUSDMessage } from './MinFromAmountUSDMessage.js' import { MissingRouteRequiredAccountMessage } from './MissingRouteRequiredAccountMessage.js' -import { ToAddressRequiredMessage } from './ToAddressRequiredMessage.js' import { useMessageQueue } from './useMessageQueue.js' type WarningMessagesProps = BoxProps & { @@ -52,8 +51,6 @@ export const WarningMessages: React.FC = ({ return case 'ACCOUNT_DEPLOYED': return - case 'TO_ADDRESS_REQUIRED': - return default: return null } diff --git a/packages/widget/src/components/Messages/useMessageQueue.ts b/packages/widget/src/components/Messages/useMessageQueue.ts index 9583dfc46..8a84ffe28 100644 --- a/packages/widget/src/components/Messages/useMessageQueue.ts +++ b/packages/widget/src/components/Messages/useMessageQueue.ts @@ -15,7 +15,6 @@ interface QueuedMessage { export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => { const { requiredToAddress, - toAddress, accountNotDeployedAtDestination, accountDeployedAtDestination, isLoading: isToAddressRequirementsLoading, @@ -69,13 +68,6 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => { }) } - if (requiredToAddress && !toAddress) { - queue.push({ - id: 'TO_ADDRESS_REQUIRED', - priority: 6, - }) - } - if ( requiredToAddress && accountDeployedAtDestination && @@ -83,7 +75,7 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => { ) { queue.push({ id: 'ACCOUNT_DEPLOYED', - priority: 7, + priority: 6, }) } @@ -95,7 +87,6 @@ export const useMessageQueue = (route?: Route, allowInteraction?: boolean) => { accountDeployedAtDestination, accountNotDeployedAtDestination, requiredToAddress, - toAddress, missingChain, missingAccountAddress, belowMinFromAmountUSD, diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx index 895044ad8..bbc7d6d5d 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx @@ -1,5 +1,26 @@ -import { cardHeaderClasses, styled } from '@mui/material' +import { Box, cardHeaderClasses, styled } from '@mui/material' import { CardHeader } from '../Card/CardHeader.js' +import { CardLabel, CardLabelTypography } from '../Card/CardLabel.js' + +export const SendToWalletCardTitleRow = styled(Box)(({ theme }) => ({ + display: 'flex', + alignItems: 'center', + justifyContent: 'space-between', + padding: theme.spacing(2, 2, 0, 2), + height: 30, +})) + +export const SendToWalletRequiredLabel = styled(CardLabel)(({ theme }) => ({ + paddingLeft: theme.spacing(1), + paddingRight: theme.spacing(1), +})) + +export const SendToWalletRequiredLabelText = styled(CardLabelTypography)( + ({ theme }) => ({ + paddingLeft: theme.spacing(0.5), + paddingRight: theme.spacing(0.5), + }) +) export const SendToWalletCardHeader = styled(CardHeader, { shouldForwardProp: (prop) => !['selected'].includes(prop as string), diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx index 322bbacc6..68667b734 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx @@ -1,6 +1,7 @@ import { useAccount } from '@lifi/wallet-management' import { useChainTypeFromAddress } from '@lifi/widget-provider' import CloseRounded from '@mui/icons-material/CloseRounded' +import WarningRounded from '@mui/icons-material/WarningRounded' import { Box, Collapse } from '@mui/material' import { useNavigate } from '@tanstack/react-router' import { type MouseEventHandler, useEffect, useRef } from 'react' @@ -20,7 +21,12 @@ import type { CardProps } from '../Card/Card.js' import { Card } from '../Card/Card.js' import { CardIconButton } from '../Card/CardIconButton.js' import { CardTitle } from '../Card/CardTitle.js' -import { SendToWalletCardHeader } from './SendToWalletButton.style.js' +import { + SendToWalletCardHeader, + SendToWalletCardTitleRow, + SendToWalletRequiredLabel, + SendToWalletRequiredLabelText, +} from './SendToWalletButton.style.js' export const SendToWalletButton: React.FC = (props) => { const { t } = useTranslation() @@ -137,7 +143,17 @@ export const SendToWalletButton: React.FC = (props) => { onClick={disabledForChanges ? undefined : handleOnClick} sx={{ width: '100%', ...props.sx }} > - {title} + + {title} + {requiredToAddress && !toAddressFieldValue ? ( + + + + {t('sendToWallet.required')} + + + ) : null} + ({ - display: 'flex', - alignItems: 'center', - borderRadius: theme.shape.borderRadius, - paddingLeft: theme.spacing(0.75), - paddingRight: theme.spacing(0.75), - marginTop: theme.spacing(1.5), - height: 24, - minWidth: 'auto', - '& .MuiTypography-root': { - maxWidth: 0, - paddingLeft: 0, - paddingRight: 0, - opacity: 0, - overflow: 'hidden', - whiteSpace: 'nowrap', - transform: 'translateX(-4px)', - transition: `max-width ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), padding ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), opacity ${animationDuration / 2}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, - }, - '&:hover .MuiTypography-root': { - maxWidth: 120, - paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5), - opacity: 1, - transform: 'translateX(0)', - }, -})) +export const SendToWalletExpandButtonChip = styled(ButtonTertiary)( + ({ theme }) => ({ + display: 'flex', + alignItems: 'center', + padding: theme.spacing(0.5, 0.75), + fontSize: 12, + fontWeight: 700, + lineHeight: 1.3334, + borderRadius: theme.shape.borderRadiusSecondary, + height: 24, + minWidth: 'auto', + '& .MuiTypography-root': { + maxWidth: 0, + paddingLeft: 0, + paddingRight: 0, + opacity: 0, + overflow: 'hidden', + whiteSpace: 'nowrap', + transform: 'translateX(-4px)', + transition: `max-width ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), padding ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), opacity ${animationDuration / 2}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, + }, + '&:hover .MuiTypography-root': { + maxWidth: 120, + paddingLeft: theme.spacing(0.5), + paddingRight: theme.spacing(0.5), + opacity: 1, + transform: 'translateX(0)', + }, + }) +) diff --git a/packages/widget/src/i18n/en.json b/packages/widget/src/i18n/en.json index ae62f63f5..19d892fb4 100644 --- a/packages/widget/src/i18n/en.json +++ b/packages/widget/src/i18n/en.json @@ -95,7 +95,6 @@ "emptyTokenListAllNetworks": "We couldn't find any tokens. Please search by contract address if your token doesn't appear, or try selecting a different chain.", "emptyTransactionHistory": "Transaction history is only stored locally and will be deleted if you clear your browser data.", "routeNotFound": "Reasons for that could be: low liquidity, amount selected is too low, gas costs are too high or there are no routes for the selected combination.", - "toAddressIsRequired": "The destination wallet address is required to proceed with the transfer.", "missingRouteRequiredAccount": "Connect your {{chainName}} wallet to proceed. {{address}}" }, "title": { @@ -344,7 +343,8 @@ "enterName": "Enter name", "noBookmarkedWallets": "No bookmarked wallets", "noConnectedWallets": "No connected wallets", - "noRecentWallets": "No recent wallets" + "noRecentWallets": "No recent wallets", + "required": "Required" }, "tokenMetric": { "currentPrice": "Current price", From 586d48ab862c80611a78c770e815efbb1a624567 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Wed, 25 Mar 2026 13:17:47 +0000 Subject: [PATCH 4/8] refactor: adjustments --- .../SendToWallet/SendToWalletButton.tsx | 2 +- .../SendToWalletExpandButton.style.ts | 38 ++++++++++--------- .../SendToWallet/SendToWalletExpandButton.tsx | 10 +++-- 3 files changed, 29 insertions(+), 21 deletions(-) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx index 68667b734..052fc5c73 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx @@ -75,7 +75,7 @@ export const SendToWalletButton: React.FC = (props) => { ? toChainId : matchingConnectedAccount ? matchingConnectedAccount.chainId - : chainType && chainType in defaultChainIdsByType + : chainType && Object.hasOwn(defaultChainIdsByType, chainType) ? defaultChainIdsByType[ chainType as keyof typeof defaultChainIdsByType ] diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts index 78e42bfd8..b7036aba0 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts @@ -1,4 +1,4 @@ -import { Box, styled, Typography } from '@mui/material' +import { Box, styled, Typography, typographyClasses } from '@mui/material' import { ButtonTertiary } from '../ButtonTertiary.js' const animationDuration = 225 @@ -8,11 +8,24 @@ export const SendToWalletExpandButtonIcon = styled(Box)({ alignItems: 'center', }) -export const SendToWalletExpandButtonLabel = styled(Typography)({ +export const SendToWalletExpandButtonLabelWrapper = styled(Box)({ + display: 'grid', + gridTemplateColumns: '0fr', + transition: `grid-template-columns ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, +}) + +export const SendToWalletExpandButtonLabel = styled(Typography)(() => ({ fontSize: 12, fontWeight: 700, - lineHeight: 1.334, -}) + lineHeight: 1.3334, + whiteSpace: 'nowrap', + overflow: 'hidden', + opacity: 0, + transform: 'translateX(-4px)', + transition: `opacity ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, +})) + +export const labelWrapperClassName = 'send-to-wallet-label-wrapper' export const SendToWalletExpandButtonChip = styled(ButtonTertiary)( ({ theme }) => ({ @@ -25,22 +38,13 @@ export const SendToWalletExpandButtonChip = styled(ButtonTertiary)( borderRadius: theme.shape.borderRadiusSecondary, height: 24, minWidth: 'auto', - '& .MuiTypography-root': { - maxWidth: 0, - paddingLeft: 0, - paddingRight: 0, - opacity: 0, - overflow: 'hidden', - whiteSpace: 'nowrap', - transform: 'translateX(-4px)', - transition: `max-width ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), padding ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), opacity ${animationDuration / 2}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, + [`&:hover .${labelWrapperClassName}`]: { + gridTemplateColumns: '1fr', }, - '&:hover .MuiTypography-root': { - maxWidth: 120, - paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5), + [`&:hover .${labelWrapperClassName} .${typographyClasses.root}`]: { opacity: 1, transform: 'translateX(0)', + marginLeft: theme.spacing(0.75), }, }) ) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx index 74cf5aad8..095cb5057 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx @@ -8,16 +8,18 @@ import { useFieldValues } from '../../stores/form/useFieldValues.js' import { DisabledUI, HiddenUI } from '../../types/widget.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' import { + labelWrapperClassName, SendToWalletExpandButtonChip, SendToWalletExpandButtonIcon, SendToWalletExpandButtonLabel, + SendToWalletExpandButtonLabelWrapper, } from './SendToWalletExpandButton.style.js' export const SendToWalletExpandButton = () => { const { t } = useTranslation() const navigate = useNavigate() - const { subvariant, subvariantOptions, toAddresses } = useWidgetConfig() - const { disabledUI, hiddenUI } = useWidgetConfig() + const { subvariant, subvariantOptions, toAddresses, disabledUI, hiddenUI } = + useWidgetConfig() const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) const { requiredToAddress } = useToAddressRequirements() @@ -48,7 +50,9 @@ export const SendToWalletExpandButton = () => { - {label} + + {label} + From 61483e01e1971d96e2dfe9b0c91358bd888821f0 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Wed, 1 Apr 2026 12:36:36 +0100 Subject: [PATCH 5/8] refactor: revert old button --- .../components/AmountInput/AmountInput.tsx | 13 +---- .../BaseTransactionButton.tsx | 2 + .../components/BaseTransactionButton/types.ts | 2 + .../SendToWalletExpandButton.style.ts | 50 ---------------- .../SendToWallet/SendToWalletExpandButton.tsx | 57 ++++++++----------- .../widget/src/pages/MainPage/MainPage.tsx | 10 +++- .../src/pages/MainPage/ReviewButton.tsx | 1 + 7 files changed, 40 insertions(+), 95 deletions(-) delete mode 100644 packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts diff --git a/packages/widget/src/components/AmountInput/AmountInput.tsx b/packages/widget/src/components/AmountInput/AmountInput.tsx index 5bfe5ed9c..f708dff43 100644 --- a/packages/widget/src/components/AmountInput/AmountInput.tsx +++ b/packages/widget/src/components/AmountInput/AmountInput.tsx @@ -18,7 +18,6 @@ import { } from '../../utils/format.js' import { fitInputText } from '../../utils/input.js' import { InputCard } from '../Card/InputCard.js' -import { SendToWalletExpandButton } from '../SendToWallet/SendToWalletExpandButton.js' import { AmountInputCardHeader, AmountInputCardTitle, @@ -47,7 +46,6 @@ export const AmountInput: React.FC = ({ formType }) => { } bottomAdornment={} disabled={disabled} /> @@ -59,18 +57,10 @@ const AmountInputBase: React.FC< CardProps & { token?: Token startAdornment?: ReactNode - endAdornment?: ReactNode bottomAdornment?: ReactNode disabled?: boolean } -> = ({ - formType, - token, - startAdornment, - endAdornment, - bottomAdornment, - disabled, -}) => { +> = ({ formType, token, startAdornment, bottomAdornment, disabled }) => { const { t } = useTranslation() const { subvariant, subvariantOptions } = useWidgetConfig() const ref = useRef(null) @@ -168,7 +158,6 @@ const AmountInputBase: React.FC< {title} - {endAdornment} diff --git a/packages/widget/src/components/BaseTransactionButton/BaseTransactionButton.tsx b/packages/widget/src/components/BaseTransactionButton/BaseTransactionButton.tsx index 8485ba28b..2c6302f4f 100644 --- a/packages/widget/src/components/BaseTransactionButton/BaseTransactionButton.tsx +++ b/packages/widget/src/components/BaseTransactionButton/BaseTransactionButton.tsx @@ -13,6 +13,7 @@ export const BaseTransactionButton: React.FC = ({ disabled, loading, route, + sx, }) => { const { t } = useTranslation() const { walletConfig } = useWidgetConfig() @@ -62,6 +63,7 @@ export const BaseTransactionButton: React.FC = ({ loading={loading} loadingPosition="center" fullWidth + sx={sx} > {getButtonText()} diff --git a/packages/widget/src/components/BaseTransactionButton/types.ts b/packages/widget/src/components/BaseTransactionButton/types.ts index dcee3bd89..c624e1be9 100644 --- a/packages/widget/src/components/BaseTransactionButton/types.ts +++ b/packages/widget/src/components/BaseTransactionButton/types.ts @@ -1,4 +1,5 @@ import type { RouteExtended } from '@lifi/sdk' +import type { SxProps, Theme } from '@mui/material' export interface BaseTransactionButtonProps { onClick?(): void @@ -6,4 +7,5 @@ export interface BaseTransactionButtonProps { disabled?: boolean loading?: boolean route?: RouteExtended + sx?: SxProps } diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts deleted file mode 100644 index b7036aba0..000000000 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.style.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { Box, styled, Typography, typographyClasses } from '@mui/material' -import { ButtonTertiary } from '../ButtonTertiary.js' - -const animationDuration = 225 - -export const SendToWalletExpandButtonIcon = styled(Box)({ - display: 'flex', - alignItems: 'center', -}) - -export const SendToWalletExpandButtonLabelWrapper = styled(Box)({ - display: 'grid', - gridTemplateColumns: '0fr', - transition: `grid-template-columns ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, -}) - -export const SendToWalletExpandButtonLabel = styled(Typography)(() => ({ - fontSize: 12, - fontWeight: 700, - lineHeight: 1.3334, - whiteSpace: 'nowrap', - overflow: 'hidden', - opacity: 0, - transform: 'translateX(-4px)', - transition: `opacity ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1), transform ${animationDuration}ms cubic-bezier(0.4, 0, 0.2, 1)`, -})) - -export const labelWrapperClassName = 'send-to-wallet-label-wrapper' - -export const SendToWalletExpandButtonChip = styled(ButtonTertiary)( - ({ theme }) => ({ - display: 'flex', - alignItems: 'center', - padding: theme.spacing(0.5, 0.75), - fontSize: 12, - fontWeight: 700, - lineHeight: 1.3334, - borderRadius: theme.shape.borderRadiusSecondary, - height: 24, - minWidth: 'auto', - [`&:hover .${labelWrapperClassName}`]: { - gridTemplateColumns: '1fr', - }, - [`&:hover .${labelWrapperClassName} .${typographyClasses.root}`]: { - opacity: 1, - transform: 'translateX(0)', - marginLeft: theme.spacing(0.75), - }, - }) -) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx index 095cb5057..9dd18b951 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx @@ -1,5 +1,7 @@ -import ChevronRightRounded from '@mui/icons-material/ChevronRightRounded' import Wallet from '@mui/icons-material/Wallet' +import Button from '@mui/material/Button' +import Collapse from '@mui/material/Collapse' +import Tooltip from '@mui/material/Tooltip' import { useNavigate } from '@tanstack/react-router' import { useTranslation } from 'react-i18next' import { useToAddressRequirements } from '../../hooks/useToAddressRequirements.js' @@ -7,37 +9,21 @@ import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.j import { useFieldValues } from '../../stores/form/useFieldValues.js' import { DisabledUI, HiddenUI } from '../../types/widget.js' import { navigationRoutes } from '../../utils/navigationRoutes.js' -import { - labelWrapperClassName, - SendToWalletExpandButtonChip, - SendToWalletExpandButtonIcon, - SendToWalletExpandButtonLabel, - SendToWalletExpandButtonLabelWrapper, -} from './SendToWalletExpandButton.style.js' export const SendToWalletExpandButton = () => { const { t } = useTranslation() const navigate = useNavigate() - const { subvariant, subvariantOptions, toAddresses, disabledUI, hiddenUI } = - useWidgetConfig() + const { toAddresses, disabledUI, hiddenUI } = useWidgetConfig() const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress) const disabledToAddress = disabledUI?.includes(DisabledUI.ToAddress) const { requiredToAddress } = useToAddressRequirements() const [toAddressValue] = useFieldValues('toAddress') - if ( - hiddenToAddress || - disabledToAddress || - toAddressValue || - requiredToAddress - ) { - return null - } - - const label = - subvariant === 'custom' && subvariantOptions?.custom === 'deposit' - ? t('header.depositTo') - : t('header.sendToWallet') + const visible = + !hiddenToAddress && + !disabledToAddress && + !toAddressValue && + !requiredToAddress const handleClick = () => navigate({ @@ -47,14 +33,21 @@ export const SendToWalletExpandButton = () => { }) return ( - - - - - {label} - - - - + + + + + ) } diff --git a/packages/widget/src/pages/MainPage/MainPage.tsx b/packages/widget/src/pages/MainPage/MainPage.tsx index 7802a7ce6..7b91bb8e9 100644 --- a/packages/widget/src/pages/MainPage/MainPage.tsx +++ b/packages/widget/src/pages/MainPage/MainPage.tsx @@ -9,6 +9,7 @@ import { PoweredBy } from '../../components/PoweredBy/PoweredBy.js' import { Routes } from '../../components/Routes/Routes.js' import { SelectChainAndToken } from '../../components/SelectChainAndToken.js' import { SendToWalletButton } from '../../components/SendToWallet/SendToWalletButton.js' +import { SendToWalletExpandButton } from '../../components/SendToWallet/SendToWalletExpandButton.js' import { useHeader } from '../../hooks/useHeader.js' import { useWideVariant } from '../../hooks/useWideVariant.js' import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js' @@ -64,7 +65,14 @@ export const MainPage: React.FC = () => { {showGasRefuelMessage ? : null} - + + + + {showPoweredBy ? : null} diff --git a/packages/widget/src/pages/MainPage/ReviewButton.tsx b/packages/widget/src/pages/MainPage/ReviewButton.tsx index 51b88c358..a56f0a253 100644 --- a/packages/widget/src/pages/MainPage/ReviewButton.tsx +++ b/packages/widget/src/pages/MainPage/ReviewButton.tsx @@ -75,6 +75,7 @@ export const ReviewButton: React.FC = () => { onClick={handleClick} disabled={currentRoute && requiredToAddress && !toAddress} route={currentRoute} + sx={{ flex: 1 }} /> ) } From 3792f86b39e60b2e44e38f8166533b0fb56eada6 Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Wed, 1 Apr 2026 12:40:51 +0100 Subject: [PATCH 6/8] refactor: styling adjustment --- .../components/SendToWallet/SendToWalletButton.style.tsx | 6 ++---- .../src/components/SendToWallet/SendToWalletButton.tsx | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx index bbc7d6d5d..19f22e2e8 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.style.tsx @@ -11,14 +11,12 @@ export const SendToWalletCardTitleRow = styled(Box)(({ theme }) => ({ })) export const SendToWalletRequiredLabel = styled(CardLabel)(({ theme }) => ({ - paddingLeft: theme.spacing(1), - paddingRight: theme.spacing(1), + padding: theme.spacing(0, 1), })) export const SendToWalletRequiredLabelText = styled(CardLabelTypography)( ({ theme }) => ({ - paddingLeft: theme.spacing(0.5), - paddingRight: theme.spacing(0.5), + padding: theme.spacing(0, 0.5), }) ) diff --git a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx index 052fc5c73..e0d372449 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletButton.tsx @@ -75,10 +75,8 @@ export const SendToWalletButton: React.FC = (props) => { ? toChainId : matchingConnectedAccount ? matchingConnectedAccount.chainId - : chainType && Object.hasOwn(defaultChainIdsByType, chainType) - ? defaultChainIdsByType[ - chainType as keyof typeof defaultChainIdsByType - ] + : chainType + ? defaultChainIdsByType[chainType] : undefined const isConnectedAccount = From ef044ab6a208f28a32a5b26c67a1f8089d5cd08e Mon Sep 17 00:00:00 2001 From: Lizaveta Miasayedava Date: Wed, 1 Apr 2026 14:13:41 +0100 Subject: [PATCH 7/8] fix: revert margin bottoms instead of gap for collapses --- .../components/AmountInput/AmountInput.tsx | 17 +++++++-- .../src/components/SelectChainAndToken.tsx | 5 ++- .../SendToWallet/SendToWalletExpandButton.tsx | 8 +++- .../widget/src/pages/MainPage/MainPage.tsx | 38 ++++++++----------- 4 files changed, 40 insertions(+), 28 deletions(-) diff --git a/packages/widget/src/components/AmountInput/AmountInput.tsx b/packages/widget/src/components/AmountInput/AmountInput.tsx index f708dff43..bd693693c 100644 --- a/packages/widget/src/components/AmountInput/AmountInput.tsx +++ b/packages/widget/src/components/AmountInput/AmountInput.tsx @@ -31,7 +31,10 @@ import { AmountInputEndAdornment } from './AmountInputEndAdornment.js' import { AmountInputStartAdornment } from './AmountInputStartAdornment.js' import { PriceFormHelperText } from './PriceFormHelperText.js' -export const AmountInput: React.FC = ({ formType }) => { +export const AmountInput: React.FC = ({ + formType, + ...props +}) => { const { disabledUI } = useWidgetConfig() const [chainId, tokenAddress] = useFieldValues( @@ -48,6 +51,7 @@ export const AmountInput: React.FC = ({ formType }) => { token={token} bottomAdornment={} disabled={disabled} + {...props} /> ) } @@ -60,7 +64,14 @@ const AmountInputBase: React.FC< bottomAdornment?: ReactNode disabled?: boolean } -> = ({ formType, token, startAdornment, bottomAdornment, disabled }) => { +> = ({ + formType, + token, + startAdornment, + bottomAdornment, + disabled, + ...props +}) => { const { t } = useTranslation() const { subvariant, subvariantOptions } = useWidgetConfig() const ref = useRef(null) @@ -155,7 +166,7 @@ const AmountInputBase: React.FC< : t('header.send') return ( - + {title} diff --git a/packages/widget/src/components/SelectChainAndToken.tsx b/packages/widget/src/components/SelectChainAndToken.tsx index 7ba63ad26..4ac80d8be 100644 --- a/packages/widget/src/components/SelectChainAndToken.tsx +++ b/packages/widget/src/components/SelectChainAndToken.tsx @@ -1,3 +1,4 @@ +import type { BoxProps } from '@mui/material' import { Box } from '@mui/material' import { ReverseTokensButton } from '../components/ReverseTokensButton/ReverseTokensButton.js' import { SelectTokenButton } from '../components/SelectTokenButton/SelectTokenButton.js' @@ -5,7 +6,7 @@ import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js' import { DisabledUI, HiddenUI } from '../types/widget.js' import { ReverseTokensButtonEmpty } from './ReverseTokensButton/ReverseTokensButton.style.js' -export const SelectChainAndToken = () => { +export const SelectChainAndToken: React.FC = (props) => { const { disabledUI, hiddenUI, subvariant } = useWidgetConfig() const hiddenReverse = @@ -23,7 +24,7 @@ export const SelectChainAndToken = () => { const showReverseButton = !hiddenToToken && !hiddenFromToken return ( - + {!hiddenFromToken ? ( ) : null} diff --git a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx index 9dd18b951..20c41daac 100644 --- a/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx +++ b/packages/widget/src/components/SendToWallet/SendToWalletExpandButton.tsx @@ -33,7 +33,13 @@ export const SendToWalletExpandButton = () => { }) return ( - +