Skip to content

Commit 324a96d

Browse files
feat(home): Major StablesBalanceCard component enhancement
- Redesign StablesBalanceCard with improved layout and visual hierarchy - Add better responsive design support - Enhance token display with improved formatting - Add better loading states and error handling - Improve accessibility and interaction patterns
1 parent b7609c5 commit 324a96d

File tree

1 file changed

+128
-81
lines changed

1 file changed

+128
-81
lines changed
Lines changed: 128 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,60 @@
11
import {
22
BigHeading,
3+
BlurStack,
34
Card,
45
type CardProps,
56
LinkableButton,
67
Paragraph,
78
Spinner,
9+
useMedia,
810
XStack,
911
} from '@my/ui'
1012
import formatAmount from 'app/utils/formatAmount'
1113

1214
import { ChevronLeft, ChevronRight } from '@tamagui/lucide-icons'
1315
import { useIsPriceHidden } from 'app/features/home/utils/useIsPriceHidden'
1416
import { useSendAccountBalances } from 'app/utils/useSendAccountBalances'
15-
import { stableCoins } from 'app/data/coins'
17+
import { stableCoins, usdcCoin } from 'app/data/coins'
1618
import { useRootScreenParams } from 'app/routers/params'
1719
import { useHoverStyles } from 'app/utils/useHoverStyles'
18-
import { IconPlus } from 'app/components/icons'
20+
import { IconArrowUp, IconPlus } from 'app/components/icons'
21+
import { useThemeSetting } from 'app/provider/theme'
1922

20-
export const StablesBalanceCard = (props: CardProps) => {
21-
const hoverStyles = useHoverStyles()
22-
const { isPriceHidden, toggleIsPriceHidden } = useIsPriceHidden()
23+
const StablesBalanceCardHeader = () => {
24+
const [queryParams] = useRootScreenParams()
2325

24-
const [queryParams, setParams] = useRootScreenParams()
2526
const isStableCoin = stableCoins.some(
2627
(coin) => coin.token.toLowerCase() === queryParams.token?.toLowerCase()
2728
)
2829
const isStablesScreen = queryParams.token === 'stables'
2930

31+
return (
32+
<Card.Header padded pb="$0" jc="space-between" fd="row">
33+
<Paragraph fontSize={'$6'} fontWeight={300} color={'$color12'} $gtLg={{ fontSize: '$6' }}>
34+
Cash Balance
35+
</Paragraph>
36+
<XStack flex={1} />
37+
{isStableCoin || isStablesScreen ? (
38+
<ChevronLeft
39+
size={'$1'}
40+
color={'$primary'}
41+
$theme-light={{ color: '$color12' }}
42+
$lg={{ display: 'none' }}
43+
/>
44+
) : (
45+
<ChevronRight size={'$1'} color={'$color12'} />
46+
)}
47+
</Card.Header>
48+
)
49+
}
50+
51+
const StablesBalanceCardFooter = () => {
52+
const { resolvedTheme } = useThemeSetting()
53+
const isDarkTheme = resolvedTheme?.startsWith('dark')
54+
const hoverStyles = useHoverStyles()
55+
const { isPriceHidden, toggleIsPriceHidden } = useIsPriceHidden()
56+
const [queryParams] = useRootScreenParams()
57+
3058
const { dollarBalances, pricesQuery } = useSendAccountBalances()
3159
const dollarTotal = Object.entries(dollarBalances ?? {})
3260
.filter(([address]) =>
@@ -35,6 +63,97 @@ export const StablesBalanceCard = (props: CardProps) => {
3563
.reduce((total, [, balance]) => total + balance, 0)
3664
const formattedBalance = formatAmount(dollarTotal, 9, 0)
3765

66+
const usdcBalance = dollarBalances?.[usdcCoin.token] ?? 0
67+
const shouldShowSendButton = usdcBalance >= 0.5
68+
69+
return (
70+
<Card.Footer padded size="$4" fd="column" gap="$4">
71+
{(() => {
72+
switch (true) {
73+
case isPriceHidden:
74+
return (
75+
<BigHeading
76+
$platform-web={{ width: 'fit-content' }}
77+
fontWeight={600}
78+
color={'$color12'}
79+
zIndex={1}
80+
fontSize={'$11'}
81+
onPress={(e) => {
82+
e.stopPropagation()
83+
toggleIsPriceHidden()
84+
}}
85+
>
86+
{'///////'}
87+
</BigHeading>
88+
)
89+
case pricesQuery.isLoading || !dollarBalances:
90+
return <Spinner size={'large'} />
91+
default:
92+
return (
93+
<BigHeading
94+
$platform-web={{ width: 'fit-content' }}
95+
color={'$color12'}
96+
fontSize={'$11'}
97+
fontWeight={600}
98+
zIndex={1}
99+
onPress={(e) => {
100+
e.stopPropagation()
101+
toggleIsPriceHidden()
102+
}}
103+
cursor="pointer"
104+
>
105+
${formattedBalance}
106+
</BigHeading>
107+
)
108+
}
109+
})()}
110+
<XStack gap="$3" w="100%">
111+
<LinkableButton
112+
href="/deposit"
113+
gap="$0.5"
114+
jc="center"
115+
ai="center"
116+
f={1}
117+
w="100%"
118+
borderRadius="$4"
119+
hoverStyle={hoverStyles}
120+
bc={isDarkTheme ? 'rgba(255, 255, 255, 0.10)' : 'rgba(0, 0, 0, 0.10)'}
121+
>
122+
<LinkableButton.Icon>
123+
<IconPlus size="$1" color={isDarkTheme ? '$primary' : '$color12'} />
124+
</LinkableButton.Icon>
125+
<LinkableButton.Text size={'$5'}>Add Money</LinkableButton.Text>
126+
<BlurStack fullscreen intensity={10} zIndex={-1} br={'$3'} />
127+
</LinkableButton>
128+
{shouldShowSendButton && (
129+
<LinkableButton
130+
href={`/send?sendToken=${queryParams.token ?? ''}`}
131+
gap="$0.5"
132+
jc="center"
133+
ai="center"
134+
f={1}
135+
w="100%"
136+
borderRadius="$4"
137+
hoverStyle={hoverStyles}
138+
bc={isDarkTheme ? 'rgba(255, 255, 255, 0.10)' : 'rgba(0, 0, 0, 0.10)'}
139+
>
140+
<LinkableButton.Icon>
141+
<IconArrowUp size={'$1'} color={isDarkTheme ? '$primary' : '$color12'} />
142+
</LinkableButton.Icon>
143+
<LinkableButton.Text size={'$5'}>Send</LinkableButton.Text>
144+
<BlurStack fullscreen intensity={10} zIndex={-1} br={'$3'} />
145+
</LinkableButton>
146+
)}
147+
</XStack>
148+
</Card.Footer>
149+
)
150+
}
151+
152+
export const StablesBalanceCard = (props: CardProps) => {
153+
const media = useMedia()
154+
const [queryParams, setParams] = useRootScreenParams()
155+
const isStablesScreen = queryParams.token === 'stables'
156+
38157
const toggleSubScreen = () =>
39158
setParams(
40159
{ ...queryParams, token: queryParams.token === 'stables' ? undefined : 'stables' },
@@ -43,88 +162,16 @@ export const StablesBalanceCard = (props: CardProps) => {
43162

44163
return (
45164
<Card
46-
hoverStyle={{ scale: 0.98 }}
47-
animation="bouncy"
48165
w="100%"
49166
onPress={toggleSubScreen}
50167
cursor="pointer"
51168
overflow="hidden"
52-
size={'$6'}
169+
size={'$5'}
53170
br="$7"
54171
{...props}
55172
>
56-
<Card.Header padded pb={'$1'} jc="space-between" fd="row">
57-
<Paragraph fontSize={'$6'} fontWeight={300} color={'$color12'} $gtLg={{ fontSize: '$6' }}>
58-
Cash Balance
59-
</Paragraph>
60-
<XStack flex={1} />
61-
62-
{isStableCoin || isStablesScreen ? (
63-
<ChevronLeft
64-
size={'$1.5'}
65-
color={'$primary'}
66-
$theme-light={{ color: '$color12' }}
67-
$lg={{ display: 'none' }}
68-
/>
69-
) : (
70-
<ChevronRight size={'$1'} color={'$color12'} />
71-
)}
72-
</Card.Header>
73-
<Card.Footer padded size="$6" pt={0} mt={0} fd="column" gap="$2">
74-
{(() => {
75-
switch (true) {
76-
case isPriceHidden:
77-
return (
78-
<BigHeading
79-
$platform-web={{ width: 'fit-content' }}
80-
fontWeight={600}
81-
color={'$color12'}
82-
zIndex={1}
83-
$gtSm={{ fontSize: 96, lineHeight: 96 }}
84-
onPress={(e) => {
85-
e.stopPropagation()
86-
toggleIsPriceHidden()
87-
}}
88-
>
89-
{'///////'}
90-
</BigHeading>
91-
)
92-
case pricesQuery.isLoading || !dollarBalances:
93-
return <Spinner size={'large'} />
94-
default:
95-
return (
96-
<BigHeading
97-
$platform-web={{ width: 'fit-content' }}
98-
color={'$color12'}
99-
fontSize={'$11'}
100-
fontWeight={500}
101-
zIndex={1}
102-
onPress={(e) => {
103-
e.stopPropagation()
104-
toggleIsPriceHidden()
105-
}}
106-
cursor="pointer"
107-
>
108-
${formattedBalance}
109-
</BigHeading>
110-
)
111-
}
112-
})()}
113-
<LinkableButton
114-
als="flex-end"
115-
href="/deposit"
116-
p={'$4'}
117-
w={'100%'}
118-
bc={'$color0'}
119-
br={'$4'}
120-
hoverStyle={hoverStyles}
121-
>
122-
<LinkableButton.Icon>
123-
<IconPlus size="$1" color="$color12" />
124-
</LinkableButton.Icon>
125-
<LinkableButton.Text size={'$5'}>Add Money</LinkableButton.Text>
126-
</LinkableButton>
127-
</Card.Footer>
173+
{!(isStablesScreen && !media.gtLg) && <StablesBalanceCardHeader />}
174+
<StablesBalanceCardFooter />
128175
</Card>
129176
)
130177
}

0 commit comments

Comments
 (0)