Skip to content

Commit f19d1c7

Browse files
committed
address feedback - phase 3
1 parent 29b6101 commit f19d1c7

File tree

7 files changed

+193
-233
lines changed

7 files changed

+193
-233
lines changed

demo/pages/ui/token/[[...params]].tsx

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -349,16 +349,6 @@ const TokenWidgetPage: NextPage = () => {
349349
lockChainId={singleChainMode ? 8453 : undefined}
350350
singleChainMode={singleChainMode}
351351
supportedWalletVMs={supportedWalletVMs}
352-
sponsoredTokens={[
353-
'792703809:EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v',
354-
'130:0x078d782b760474a361dda0af3839290b0ef57ad6',
355-
'103665049:0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC',
356-
'8453:0x833589fcd6edb6e08f4c7c32d4f71b54bda02913',
357-
'43114:0xb97ef9ef8734c71904d8002f8b6bc66dd9c48a6e',
358-
'137:0x3c499c542cef5e3811e1192ce70d8cc03d5c3359',
359-
'42161:0xaf88d065e77c8cc2239327c5edb3a432268e5831',
360-
'10:0x0b2c639c533813f4aa9d7837caf62653d097ff85'
361-
]}
362352
toToken={toToken}
363353
setToToken={setToToken}
364354
fromToken={fromToken}

packages/ui/src/components/common/TokenSelector/PaymentMethod.tsx

Lines changed: 88 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,91 @@ const PaymentMethod: FC<PaymentMethodProps> = ({
884884
)
885885
}
886886

887+
// Chain Filter Trigger Component
888+
type ChainFilterTriggerProps = {
889+
value: ChainFilterValue
890+
open: boolean
891+
}
892+
893+
const ChainFilterTrigger: FC<ChainFilterTriggerProps> = ({ value, open }) => (
894+
<Button
895+
aria-label="Chain filter"
896+
color="ghost"
897+
size="none"
898+
css={{
899+
display: 'flex',
900+
alignItems: 'center',
901+
gap: '6px',
902+
height: 40,
903+
px: '12px',
904+
cursor: 'pointer',
905+
backgroundColor: 'dropdown-background',
906+
borderRadius: 'dropdown-border-radius',
907+
flexShrink: 0
908+
}}
909+
>
910+
{value.id ? (
911+
<ChainIcon
912+
chainId={value.id}
913+
width={20}
914+
height={20}
915+
css={{ borderRadius: 4, overflow: 'hidden' }}
916+
/>
917+
) : (
918+
<AllChainsLogo style={{ width: 20, height: 20 }} />
919+
)}
920+
<Box css={{ color: 'gray9' }}>
921+
<FontAwesomeIcon
922+
icon={faChevronDown}
923+
width={12}
924+
height={12}
925+
style={{
926+
transform: open ? 'rotate(180deg)' : 'rotate(0)',
927+
transition: 'transform 0.2s'
928+
}}
929+
/>
930+
</Box>
931+
</Button>
932+
)
933+
934+
// Chain Search Input Component
935+
type ChainSearchInputProps = {
936+
value: string
937+
onChange: (value: string) => void
938+
}
939+
940+
const ChainSearchInput: FC<ChainSearchInputProps> = ({ value, onChange }) => (
941+
<Input
942+
placeholder="Search for a chain"
943+
icon={
944+
<Box css={{ color: 'gray9' }}>
945+
<FontAwesomeIcon
946+
icon={faMagnifyingGlass}
947+
width={16}
948+
height={16}
949+
/>
950+
</Box>
951+
}
952+
containerCss={{
953+
width: '100%',
954+
height: 40,
955+
mb: '2'
956+
}}
957+
css={{
958+
width: '100%',
959+
_placeholder_parent: {
960+
textOverflow: 'ellipsis'
961+
},
962+
'--borderColor': 'colors.subtle-border-color',
963+
border: '1px solid var(--borderColor)',
964+
backgroundColor: 'modal-background'
965+
}}
966+
value={value}
967+
onChange={(e) => onChange((e.target as HTMLInputElement).value)}
968+
onKeyDown={(e) => e.stopPropagation()}
969+
/>
970+
)
971+
887972
// Compact Chain Filter Component
888973
type CompactChainFilterProps = {
889974
options: ChainFilterValue[]
@@ -936,46 +1021,7 @@ const CompactChainFilter: FC<CompactChainFilterProps> = ({
9361021
<Dropdown
9371022
open={open}
9381023
onOpenChange={(open) => setOpen(open)}
939-
trigger={
940-
<Button
941-
aria-label="Chain filter"
942-
color="ghost"
943-
size="none"
944-
css={{
945-
display: 'flex',
946-
alignItems: 'center',
947-
gap: '6px',
948-
height: 40,
949-
px: '12px',
950-
cursor: 'pointer',
951-
backgroundColor: 'dropdown-background',
952-
borderRadius: 'dropdown-border-radius',
953-
flexShrink: 0
954-
}}
955-
>
956-
{value.id ? (
957-
<ChainIcon
958-
chainId={value.id}
959-
width={20}
960-
height={20}
961-
css={{ borderRadius: 4, overflow: 'hidden' }}
962-
/>
963-
) : (
964-
<AllChainsLogo style={{ width: 20, height: 20 }} />
965-
)}
966-
<Box css={{ color: 'gray9' }}>
967-
<FontAwesomeIcon
968-
icon={faChevronDown}
969-
width={12}
970-
height={12}
971-
style={{
972-
transform: open ? 'rotate(180deg)' : 'rotate(0)',
973-
transition: 'transform 0.2s'
974-
}}
975-
/>
976-
</Box>
977-
</Button>
978-
}
1024+
trigger={<ChainFilterTrigger value={value} open={open} />}
9791025
contentProps={{
9801026
align: 'end',
9811027
avoidCollisions: false,
@@ -988,36 +1034,9 @@ const CompactChainFilter: FC<CompactChainFilterProps> = ({
9881034
}}
9891035
>
9901036
<Flex direction="column" css={{ p: '2' }}>
991-
<Input
992-
placeholder="Search for a chain"
993-
icon={
994-
<Box css={{ color: 'gray9' }}>
995-
<FontAwesomeIcon
996-
icon={faMagnifyingGlass}
997-
width={16}
998-
height={16}
999-
/>
1000-
</Box>
1001-
}
1002-
containerCss={{
1003-
width: '100%',
1004-
height: 40,
1005-
mb: '2'
1006-
}}
1007-
css={{
1008-
width: '100%',
1009-
_placeholder_parent: {
1010-
textOverflow: 'ellipsis'
1011-
},
1012-
'--borderColor': 'colors.subtle-border-color',
1013-
border: '1px solid var(--borderColor)',
1014-
backgroundColor: 'modal-background'
1015-
}}
1037+
<ChainSearchInput
10161038
value={chainSearchInput}
1017-
onChange={(e) =>
1018-
setChainSearchInput((e.target as HTMLInputElement).value)
1019-
}
1020-
onKeyDown={(e) => e.stopPropagation()}
1039+
onChange={setChainSearchInput}
10211040
/>
10221041
<Flex
10231042
direction="column"

packages/ui/src/components/widgets/SwapButton.tsx

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ type SwapButtonProps = {
1010
onConnectWallet?: () => void
1111
onAnalyticEvent?: (eventName: string, data?: any) => void
1212
onClick: () => void
13-
context: 'Swap' | 'Deposit' | 'Withdraw'
14-
showHighPriceImpactWarning: boolean
13+
context: 'Swap' | 'Deposit' | 'Withdraw' | 'Buy' | 'Sell'
14+
showHighPriceImpactWarning?: boolean
15+
disableSwapButton?: boolean
16+
tokenWidgetMode?: boolean
17+
hasValidAmount?: boolean
1518
} & Pick<
1619
ChildrenProps,
1720
| 'quote'
@@ -35,7 +38,10 @@ const SwapButton: FC<SwapButtonProps> = ({
3538
isValidFromAddress,
3639
isValidToAddress,
3740
context,
38-
showHighPriceImpactWarning,
41+
showHighPriceImpactWarning = false,
42+
disableSwapButton = false,
43+
tokenWidgetMode = false,
44+
hasValidAmount = true,
3945
onConnectWallet,
4046
quote,
4147
address,
@@ -58,39 +64,69 @@ const SwapButton: FC<SwapButtonProps> = ({
5864
!quote ||
5965
Number(debouncedInputAmountValue) === 0 ||
6066
Number(debouncedOutputAmountValue) === 0
67+
68+
const isWalletSelectionPrompt =
69+
tokenWidgetMode && (ctaCopy.includes('Select') || ctaCopy.includes('Enter'))
70+
const isSelectTokenPrompt = tokenWidgetMode && ctaCopy === 'Select a token'
71+
72+
const buttonDisabled = tokenWidgetMode
73+
? (disableSwapButton ||
74+
isFetchingQuote ||
75+
isSelectTokenPrompt ||
76+
(!isWalletSelectionPrompt && !hasValidAmount))
77+
: (isFetchingQuote ||
78+
(isValidToAddress &&
79+
(isValidFromAddress || !fromChainWalletVMSupported) &&
80+
(invalidAmount ||
81+
hasInsufficientBalance ||
82+
isInsufficientLiquidityError ||
83+
transactionModalOpen ||
84+
depositAddressModalOpen ||
85+
isSameCurrencySameRecipientSwap ||
86+
!recipientWalletSupportsChain ||
87+
disableSwapButton)))
88+
89+
const buttonLabel = tokenWidgetMode && isFetchingQuote && hasValidAmount
90+
? 'Fetching quote'
91+
: ctaCopy
6192

6293
return (
6394
<Button
64-
css={{ justifyContent: 'center' }}
95+
css={{
96+
justifyContent: 'center',
97+
width: tokenWidgetMode ? '100%' : undefined,
98+
textTransform: tokenWidgetMode ? 'uppercase' : undefined,
99+
fontFamily: tokenWidgetMode ? 'heading' : undefined,
100+
fontWeight: tokenWidgetMode ? 700 : undefined,
101+
fontStyle: tokenWidgetMode ? 'var(--relay-fonts-button-cta-font-style, italic)' : undefined
102+
}}
65103
color={showHighPriceImpactWarning ? 'error' : 'primary'}
66104
aria-label={context}
67105
cta={true}
68-
disabled={
69-
isFetchingQuote ||
70-
(isValidToAddress &&
71-
(isValidFromAddress || !fromChainWalletVMSupported) &&
72-
(invalidAmount ||
73-
hasInsufficientBalance ||
74-
isInsufficientLiquidityError ||
75-
transactionModalOpen ||
76-
depositAddressModalOpen ||
77-
isSameCurrencySameRecipientSwap ||
78-
!recipientWalletSupportsChain))
79-
}
80-
data-testid="swap-button"
106+
disabled={buttonDisabled}
107+
data-testid={tokenWidgetMode ? "token-action-button" : "swap-button"}
81108
onClick={() => {
82-
onClick()
109+
if (!buttonDisabled) {
110+
onClick()
111+
}
83112
}}
84113
>
85-
{ctaCopy}
114+
{buttonLabel}
86115
</Button>
87116
)
88117
}
89118

90119
return (
91120
<Button
92121
cta={true}
93-
css={{ justifyContent: 'center' }}
122+
css={{
123+
justifyContent: 'center',
124+
width: tokenWidgetMode ? '100%' : undefined,
125+
textTransform: tokenWidgetMode ? 'uppercase' : undefined,
126+
fontFamily: tokenWidgetMode ? 'heading' : undefined,
127+
fontWeight: tokenWidgetMode ? 700 : undefined,
128+
fontStyle: tokenWidgetMode ? 'var(--relay-fonts-button-cta-font-style, italic)' : undefined
129+
}}
94130
aria-label="Connect wallet"
95131
onClick={() => {
96132
if (!onConnectWallet) {
@@ -102,7 +138,7 @@ const SwapButton: FC<SwapButtonProps> = ({
102138
context
103139
})
104140
}}
105-
data-testid="widget-connect-wallet-button"
141+
data-testid={tokenWidgetMode ? "token-widget-connect-wallet-button" : "widget-connect-wallet-button"}
106142
>
107143
Connect Wallet
108144
</Button>

packages/ui/src/components/widgets/TokenWidget/BuyTabContent.tsx

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import type { TradeType, ChildrenProps } from './widget/TokenWidgetRenderer.js'
1818
import type { Token, LinkedWallet } from '../../../types/index.js'
1919
import type { RelayChain } from '@relayprotocol/relay-sdk'
2020
import { isDeadAddress, tronDeadAddress } from '@relayprotocol/relay-sdk'
21-
import TokenActionButton from './TokenActionButton.js'
21+
import SwapButton from '../SwapButton.js'
2222
import { PaymentMethodTrigger } from '../../common/TokenSelector/triggers/PaymentMethodTrigger.js'
2323
import AmountSectionHeader from './AmountSectionHeader.js'
2424
import AmountModeToggle from './AmountModeToggle.js'
@@ -255,23 +255,9 @@ const BuyTabContent: FC<BuyTabContentProps> = ({
255255
const currencyInAmountUsd = quote?.details?.currencyIn?.amountUsd
256256
const currencyInAmountFormatted = quote?.details?.currencyIn?.amountFormatted
257257

258-
// Only show skeleton on initial load, not on subsequent fetches
259258
const isLoadingPayWith =
260259
hasValidOutputAmount && isFetchingQuote && fromToken && !currencyInAmountUsd
261260

262-
const disableActionButton =
263-
isFetchingQuote ||
264-
(isValidToAddress &&
265-
(isValidFromAddress || !fromChainWalletVMSupported) &&
266-
(invalidAmount ||
267-
hasInsufficientBalance ||
268-
isInsufficientLiquidityError ||
269-
transactionModalOpen ||
270-
depositAddressModalOpen ||
271-
isSameCurrencySameRecipientSwap ||
272-
!recipientWalletSupportsChain ||
273-
disableSwapButton))
274-
275261
return (
276262
<TabsContent value="buy">
277263
<SectionContainer
@@ -590,20 +576,36 @@ const BuyTabContent: FC<BuyTabContentProps> = ({
590576
</Flex>
591577

592578
<Flex css={{ width: '100%' }}>
593-
<TokenActionButton
579+
<SwapButton
580+
context="Buy"
581+
transactionModalOpen={transactionModalOpen}
582+
depositAddressModalOpen={depositAddressModalOpen}
583+
showHighPriceImpactWarning={showHighPriceImpactWarning}
584+
disableSwapButton={disableSwapButton}
585+
tokenWidgetMode={true}
586+
hasValidAmount={!invalidAmount}
587+
quote={quote}
588+
address={address}
589+
hasInsufficientBalance={hasInsufficientBalance}
590+
isInsufficientLiquidityError={isInsufficientLiquidityError}
591+
debouncedInputAmountValue={debouncedInputAmountValue}
592+
debouncedOutputAmountValue={debouncedOutputAmountValue}
593+
isSameCurrencySameRecipientSwap={isSameCurrencySameRecipientSwap}
594+
ctaCopy={displayCta}
595+
isValidFromAddress={isValidFromAddress}
596+
isValidToAddress={isValidToAddress}
597+
fromChainWalletVMSupported={fromChainWalletVMSupported}
598+
recipientWalletSupportsChain={recipientWalletSupportsChain}
599+
isFetchingQuote={isFetchingQuote}
594600
onClick={() => {
595601
onAnalyticEvent?.('TOKEN_BUY_CLICKED', {
596602
token: toToken,
597603
amount: amountOutputValue
598604
})
599605
onPrimaryAction()
600606
}}
601-
ctaCopy={displayCta}
602-
disabled={disableActionButton}
603-
isFetchingQuote={isFetchingQuote}
604-
hasValidAmount={!invalidAmount}
605607
onConnectWallet={onConnectWallet}
606-
address={address}
608+
onAnalyticEvent={onAnalyticEvent}
607609
/>
608610
</Flex>
609611

0 commit comments

Comments
 (0)