Skip to content

Commit 73e5994

Browse files
perf(accessibility): fix iOS accessibility in Bridge token selector components
- BridgeTokenSelector, TokenButton, TokenSelectorItem: Pressable → TouchableOpacity Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 9e6acf5 commit 73e5994

3 files changed

Lines changed: 81 additions & 64 deletions

File tree

app/components/UI/Bridge/components/BridgeTokenSelector/BridgeTokenSelector.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,15 @@ export const BridgeTokenSelector: React.FC = () => {
546546
ListFooterComponent={renderFooter}
547547
ListEmptyComponent={renderEmptyState}
548548
onLayout={handleFlatListLayout}
549+
initialNumToRender={8}
550+
maxToRenderPerBatch={5}
551+
windowSize={5}
552+
removeClippedSubviews
553+
getItemLayout={(_data, index) => ({
554+
length: ESTIMATED_ITEM_HEIGHT,
555+
offset: ESTIMATED_ITEM_HEIGHT * index,
556+
index,
557+
})}
549558
/>
550559
</SafeAreaView>
551560
);

app/components/UI/Bridge/components/TokenButton.tsx

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ import Text, {
99
} from '../../../../component-library/components/Texts/Text';
1010
import { useStyles } from '../../../../component-library/hooks';
1111
import { Theme } from '../../../../util/theme/models';
12-
import { Box } from '../../Box/Box';
13-
import { FlexDirection, AlignItems, JustifyContent } from '../../Box/box.types';
1412
import BadgeWrapper, {
1513
BadgePosition,
1614
} from '../../../../component-library/components/Badges/BadgeWrapper';
@@ -42,6 +40,10 @@ const createStyles = (params: StylesParams) => {
4240
borderRadius: 16,
4341
},
4442
pillContainer: {
43+
flexDirection: 'row' as const,
44+
alignItems: 'flex-end' as const,
45+
justifyContent: 'flex-end' as const,
46+
gap: 8,
4547
backgroundColor: theme.colors.background.muted,
4648
borderRadius: 100,
4749
paddingLeft: 8,
@@ -67,31 +69,27 @@ export const TokenButton: React.FC<TokenProps> = ({
6769
}) => {
6870
const { styles } = useStyles(createStyles, {});
6971
return (
70-
<TouchableOpacity onPress={onPress} testID={testID}>
71-
<Box
72-
style={styles.pillContainer}
73-
flexDirection={FlexDirection.Row}
74-
alignItems={AlignItems.flexEnd}
75-
justifyContent={JustifyContent.flexEnd}
76-
gap={8}
72+
<TouchableOpacity
73+
onPress={onPress}
74+
testID={testID}
75+
style={styles.pillContainer}
76+
>
77+
<BadgeWrapper
78+
badgePosition={BadgePosition.BottomRight}
79+
badgeElement={
80+
<Badge
81+
variant={BadgeVariant.Network}
82+
imageSource={networkImageSource}
83+
name={networkName}
84+
/>
85+
}
7786
>
78-
<BadgeWrapper
79-
badgePosition={BadgePosition.BottomRight}
80-
badgeElement={
81-
<Badge
82-
variant={BadgeVariant.Network}
83-
imageSource={networkImageSource}
84-
name={networkName}
85-
/>
86-
}
87-
>
88-
<TokenIcon symbol={symbol} icon={iconUrl} style={styles.icon} />
89-
</BadgeWrapper>
87+
<TokenIcon symbol={symbol} icon={iconUrl} style={styles.icon} />
88+
</BadgeWrapper>
9089

91-
<Text style={styles.tokenSymbol} variant={TextVariant.HeadingLG}>
92-
{symbol}
93-
</Text>
94-
</Box>
90+
<Text style={styles.tokenSymbol} variant={TextVariant.HeadingLG}>
91+
{symbol}
92+
</Text>
9593
</TouchableOpacity>
9694
);
9795
};

app/components/UI/Bridge/components/TokenSelectorItem.tsx

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,13 @@ const createStyles = ({
7272
flex: 1,
7373
flexShrink: 1,
7474
minWidth: 0,
75-
marginLeft: 12,
75+
marginLeft: 8,
7676
},
7777
container: {
7878
backgroundColor: vars.isSelected
7979
? theme.colors.primary.muted
8080
: theme.colors.background.default,
8181
paddingVertical: 4,
82-
minHeight: 72,
8382
paddingLeft: 16,
8483
paddingRight: 10,
8584
},
@@ -95,7 +94,7 @@ const createStyles = ({
9594
itemWrapper: {
9695
flex: 1,
9796
flexDirection: 'row',
98-
paddingVertical: 12,
97+
paddingVertical: 10,
9998
alignItems: 'flex-start',
10099
},
101100
tokenMainInfo: {
@@ -258,7 +257,28 @@ const TokenBalanceView = ({
258257
);
259258
};
260259

261-
export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
260+
const formatTokenBalance = (balance: string): string => {
261+
const numericBalance = Number(balance);
262+
if (numericBalance === 0) {
263+
return '0';
264+
}
265+
if (numericBalance < 0.00001) {
266+
return '< 0.00001';
267+
}
268+
return parseAmount(balance, 5) || balance;
269+
};
270+
271+
const TOP_ROW_BALANCE_TEXT_STYLE = {
272+
textVariant: TextVariant.BodyMDMedium,
273+
textColor: TextColor.Default,
274+
} as const;
275+
276+
const BOTTOM_ROW_BALANCE_TEXT_STYLE = {
277+
textVariant: TextVariant.BodyMD,
278+
textColor: TextColor.Alternative,
279+
} as const;
280+
281+
const TokenSelectorItemInner: React.FC<TokenSelectorItemProps> = ({
262282
token,
263283
onPress,
264284
networkName,
@@ -288,17 +308,6 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
288308

289309
const fiatValue = token.balanceFiat;
290310

291-
const formatTokenBalance = (balance: string): string => {
292-
const numericBalance = Number(balance);
293-
if (numericBalance === 0) {
294-
return '0';
295-
}
296-
if (numericBalance < 0.00001) {
297-
return '< 0.00001';
298-
}
299-
return parseAmount(balance, 5) || balance;
300-
};
301-
302311
const selectedVariant =
303312
variant ??
304313
TOKEN_SELECTOR_BALANCE_LAYOUT_VARIANTS[
@@ -315,27 +324,10 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
315324

316325
const isNative = token.address === ethers.constants.AddressZero;
317326

318-
// to check if the token is a stock by checking if the name includes 'ondo' or 'stock'
319327
const { isStockToken } = useRWAToken();
320328

321329
const fiatBalance = shouldShowBalance ? fiatValue : undefined;
322330
const tokenBalance = shouldShowBalance ? cryptoBalance : undefined;
323-
const topRowBalanceTextStyle = {
324-
textVariant: TextVariant.BodyMDMedium,
325-
textColor: TextColor.Default,
326-
};
327-
const bottomRowBalanceTextStyle = {
328-
textVariant: TextVariant.BodySM,
329-
textColor: TextColor.Alternative,
330-
};
331-
const topRowTokenBalanceTextStyle = {
332-
...topRowBalanceTextStyle,
333-
...tokenBalanceTextProps,
334-
};
335-
const bottomRowTokenBalanceTextStyle = {
336-
...bottomRowBalanceTextStyle,
337-
...tokenBalanceTextProps,
338-
};
339331

340332
const label = token.accountType
341333
? ACCOUNT_TYPE_LABELS[token.accountType]
@@ -360,6 +352,7 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
360352

361353
return (
362354
<Box
355+
accessible={false}
363356
flexDirection={FlexDirection.Row}
364357
alignItems={AlignItems.center}
365358
style={styles.container}
@@ -373,6 +366,7 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
373366
testID={getAssetTestId(`${token.chainId}-${token.symbol}`)}
374367
>
375368
<Box
369+
accessible={false}
376370
flexDirection={FlexDirection.Row}
377371
alignItems={AlignItems.center}
378372
gap={4}
@@ -396,19 +390,20 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
396390
tokenAvatar
397391
)}
398392

399-
{/* Token symbol/name on the left, balances on the right (extension layout pattern) */}
400393
<Box
394+
accessible={false}
401395
style={styles.tokenInfo}
402396
flexDirection={FlexDirection.Column}
403397
gap={4}
404398
>
405399
<Box
400+
accessible={false}
406401
flexDirection={FlexDirection.Row}
407402
alignItems={AlignItems.center}
408403
justifyContent={JustifyContent.spaceBetween}
409404
>
410-
<Box style={styles.tokenMainInfo} gap={4}>
411-
<Box style={styles.tokenSymbolRow}>
405+
<Box accessible={false} style={styles.tokenMainInfo} gap={4}>
406+
<Box accessible={false} style={styles.tokenSymbolRow}>
412407
<Text
413408
variant={TextVariant.BodyMDMedium}
414409
numberOfLines={1}
@@ -462,19 +457,20 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
462457
balance={tokenBalance}
463458
isSelected={shouldShowSelectedStyle}
464459
textStyle={styles.rightValue}
465-
{...topRowTokenBalanceTextStyle}
460+
{...TOP_ROW_BALANCE_TEXT_STYLE}
466461
/>
467462
) : (
468463
<FiatBalanceView
469464
balance={fiatBalance}
470465
isSelected={shouldShowSelectedStyle}
471466
textStyle={styles.rightValue}
472-
{...topRowBalanceTextStyle}
467+
{...TOP_ROW_BALANCE_TEXT_STYLE}
473468
/>
474469
)}
475470
</Box>
476471

477472
<Box
473+
accessible={false}
478474
flexDirection={FlexDirection.Row}
479475
alignItems={AlignItems.center}
480476
justifyContent={JustifyContent.spaceBetween}
@@ -503,14 +499,14 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
503499
balance={fiatBalance}
504500
isSelected={shouldShowSelectedStyle}
505501
textStyle={styles.rightValue}
506-
{...bottomRowBalanceTextStyle}
502+
{...BOTTOM_ROW_BALANCE_TEXT_STYLE}
507503
/>
508504
) : (
509505
<TokenBalanceView
510506
balance={tokenBalance}
511507
isSelected={shouldShowSelectedStyle}
512508
textStyle={styles.rightValue}
513-
{...bottomRowTokenBalanceTextStyle}
509+
{...BOTTOM_ROW_BALANCE_TEXT_STYLE}
514510
/>
515511
)}
516512
</Box>
@@ -523,3 +519,17 @@ export const TokenSelectorItem: React.FC<TokenSelectorItemProps> = ({
523519
</Box>
524520
);
525521
};
522+
523+
export const TokenSelectorItem = React.memo(
524+
TokenSelectorItemInner,
525+
(prev, next) =>
526+
prev.onPress === next.onPress &&
527+
prev.token.address === next.token.address &&
528+
prev.token.chainId === next.token.chainId &&
529+
prev.token.balance === next.token.balance &&
530+
prev.token.balanceFiat === next.token.balanceFiat &&
531+
prev.isSelected === next.isSelected &&
532+
prev.isNoFeeAsset === next.isNoFeeAsset &&
533+
prev.shouldShowBalance === next.shouldShowBalance &&
534+
prev.networkName === next.networkName,
535+
);

0 commit comments

Comments
 (0)