Skip to content

Commit f837940

Browse files
committed
refactor: token list + button
1 parent 41da6a8 commit f837940

File tree

2 files changed

+94
-106
lines changed

2 files changed

+94
-106
lines changed

app/components/tokenListItem.tsx

Lines changed: 54 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { IconChevronsRight } from '@tabler/icons-react';
22
import { Flex } from 'antd';
33
import Image from 'next/image';
4-
import { useState } from 'react';
54
import { twMerge } from 'tailwind-merge';
65
import { Token } from '../hooks/useData';
76
import { Data, Dataset } from '../utils/types';
@@ -18,65 +17,11 @@ const t: Dataset = {
1817

1918
interface TokenListItemProps {
2019
asset: Token;
21-
index: number;
22-
selectedIndex?: number;
23-
hasLoaded: boolean;
24-
tokens: Token[];
25-
tokenDetails: Data[];
26-
total: number;
27-
onSelectedIndexChange: (index: number | undefined) => void;
28-
}
29-
30-
interface TokenDetailsButtonProps {
31-
index: number;
32-
selectedIndex?: number;
3320
hasLoaded: boolean;
34-
isTokenDetailsOpen: boolean;
3521
tokens: Token[];
3622
tokenDetails: Data[];
3723
total: number;
38-
onSelectedIndexChange: (index: number | undefined) => void;
39-
onTokenDetailsOpenChange: (isOpen: boolean) => void;
40-
}
41-
42-
function TokenDetailsButton({
43-
index,
44-
selectedIndex,
45-
hasLoaded,
46-
isTokenDetailsOpen,
47-
tokens,
48-
tokenDetails,
49-
total,
50-
onSelectedIndexChange,
51-
onTokenDetailsOpenChange,
52-
}: TokenDetailsButtonProps) {
53-
return (
54-
<div className="hidden xs:flex items-center mx-0 xs:mx-2 md:mx-4 w-[50px] h-[50px] justify-center">
55-
<IconChevronsRight
56-
className={twMerge(
57-
'h-8 w-8 text-theme-content-strong dark:text-dark-theme-content-strong',
58-
'transition-all duration-500 group-hover:animate-pulse',
59-
index === selectedIndex ? 'opacity-100' : 'opacity-0 group-hover:opacity-100',
60-
)}
61-
onClick={e => {
62-
e.stopPropagation();
63-
onSelectedIndexChange(index);
64-
onTokenDetailsOpenChange(true);
65-
}}
66-
/>
67-
{hasLoaded ? (
68-
<TokenDetails
69-
isOpen={isTokenDetailsOpen}
70-
onClose={() => onTokenDetailsOpenChange(false)}
71-
tokens={tokens}
72-
data={tokenDetails}
73-
total={total}
74-
selectedIndex={selectedIndex}
75-
onSelectedIndexChange={onSelectedIndexChange}
76-
/>
77-
) : null}
78-
</div>
79-
);
24+
setIsTokenDetailsOpen: (isOpen: boolean) => void;
8025
}
8126

8227
export function TokenListLoading() {
@@ -100,36 +45,9 @@ export function TokenListLoading() {
10045
);
10146
}
10247

103-
export function TokenListItem({
104-
asset,
105-
index,
106-
selectedIndex,
107-
hasLoaded,
108-
tokens,
109-
tokenDetails,
110-
total,
111-
onSelectedIndexChange,
112-
}: TokenListItemProps) {
113-
const [isTokenDetailsOpen, setIsTokenDetailsOpen] = useState(false);
114-
48+
export function TokenListItem({ asset, hasLoaded }: TokenListItemProps) {
11549
return (
116-
<div
117-
key={asset.label}
118-
className={twMerge(
119-
'flex w-full border-b-2 last:border-b-0 border-theme-border dark:border-dark-theme-border',
120-
'group cursor-pointer select-none touch-none transition-colors duration-200 py-4',
121-
selectedIndex === index
122-
? 'bg-theme-background-subtle dark:bg-dark-theme-background-subtle'
123-
: 'hover:bg-theme-background-subtle dark:hover:bg-dark-theme-background-subtle [@media(hover:none)]:hover:bg-transparent [@media(hover:none)]:dark:hover:bg-transparent',
124-
)}
125-
onClick={() => onSelectedIndexChange(selectedIndex === index ? undefined : index)}
126-
onContextMenu={e => {
127-
e.preventDefault();
128-
e.stopPropagation();
129-
onSelectedIndexChange(index);
130-
setIsTokenDetailsOpen(true);
131-
}}
132-
>
50+
<div className="flex w-full">
13351
<Image
13452
className="rounded-full w-[50px] h-[50px] hidden 2xs:flex items-center mx-0 xs:mx-2 md:mx-4"
13553
src={asset.image}
@@ -168,17 +86,58 @@ export function TokenListItem({
16886
</Flex>
16987
<Privacy className="font-bold text-lg text-right" amount={asset.total} />
17088
</div>
171-
<TokenDetailsButton
172-
index={index}
173-
selectedIndex={selectedIndex}
174-
hasLoaded={hasLoaded}
175-
isTokenDetailsOpen={isTokenDetailsOpen}
176-
tokens={tokens}
177-
tokenDetails={tokenDetails}
178-
total={total}
179-
onSelectedIndexChange={onSelectedIndexChange}
180-
onTokenDetailsOpenChange={setIsTokenDetailsOpen}
89+
</div>
90+
);
91+
}
92+
93+
interface TokenDetailsButtonProps {
94+
index: number;
95+
selectedIndex?: number;
96+
hasLoaded: boolean;
97+
isTokenDetailsOpen: boolean;
98+
tokens: Token[];
99+
tokenDetails: Data[];
100+
total: number;
101+
onSelectedIndexChange: (index: number | undefined) => void;
102+
onTokenDetailsOpenChange: (isOpen: boolean) => void;
103+
}
104+
105+
export function TokenDetailsButton({
106+
index,
107+
selectedIndex,
108+
hasLoaded,
109+
isTokenDetailsOpen,
110+
tokens,
111+
tokenDetails,
112+
total,
113+
onSelectedIndexChange,
114+
onTokenDetailsOpenChange,
115+
}: TokenDetailsButtonProps) {
116+
return (
117+
<div className="hidden xs:flex self-center mx-0 xs:mx-2 md:mx-4 w-[50px] h-full justify-center">
118+
<IconChevronsRight
119+
className={twMerge(
120+
'h-8 w-8 text-theme-content-strong dark:text-dark-theme-content-strong',
121+
'transition-all duration-500 group-hover:animate-pulse',
122+
index === selectedIndex ? 'opacity-100' : 'opacity-0 group-hover:opacity-100',
123+
)}
124+
onClick={e => {
125+
e.stopPropagation();
126+
onSelectedIndexChange(index);
127+
onTokenDetailsOpenChange(true);
128+
}}
181129
/>
130+
{hasLoaded ? (
131+
<TokenDetails
132+
isOpen={isTokenDetailsOpen}
133+
onClose={() => onTokenDetailsOpenChange(false)}
134+
tokens={tokens}
135+
data={tokenDetails}
136+
total={total}
137+
selectedIndex={selectedIndex}
138+
onSelectedIndexChange={onSelectedIndexChange}
139+
/>
140+
) : null}
182141
</div>
183142
);
184143
}

app/pages/portfolio.tsx

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import { AreaChart, SparkAreaChart } from '@tremor/react';
22
import { Divider, Flex } from 'antd';
33
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4+
import { twMerge } from 'tailwind-merge';
45
import { CollapsiblePanel } from '../components/collapsiblePanel';
56
import GainsBar from '../components/gainsBar';
67
import { Privacy, PrivacyButton, toPrivacy } from '../components/privacy';
78
import RatioBadge from '../components/ratioBadge';
89
import { TokenGraphs } from '../components/tokenGraphs';
9-
import { TokenListItem, TokenListLoading } from '../components/tokenListItem';
10+
import { TokenDetailsButton, TokenListItem, TokenListLoading } from '../components/tokenListItem';
1011
import { LoadingMetric, Title } from '../components/typography';
1112
import { usePrivacy } from '../contexts/privacyProvider';
1213
import type { PortfolioToken, Token, UserHistoric } from '../hooks/useData';
@@ -53,6 +54,8 @@ export default function Portfolio() {
5354
const { wallet, setWallet, portfolio, setPortfolio, userHistoric, setUserHistoric, transactions, setTransactions } =
5455
useData();
5556

57+
const [isTokenDetailsOpen, setIsTokenDetailsOpen] = useState(false);
58+
5659
const [hasLoaded, setHasLoaded] = useState(false);
5760
const [selectedIndex, setSelectedIndex] = useState<number>();
5861
const [isMobile, setIsMobile] = useState(false);
@@ -337,17 +340,43 @@ export default function Portfolio() {
337340

338341
{wallet ? (
339342
wallet.map((asset, index) => (
340-
<TokenListItem
343+
<div
341344
key={asset.label}
342-
asset={asset}
343-
index={index}
344-
selectedIndex={selectedIndex}
345-
hasLoaded={!!transactions}
346-
tokens={wallet}
347-
tokenDetails={tokenDetails}
348-
total={portfolio?.total ?? 0}
349-
onSelectedIndexChange={setSelectedIndex}
350-
/>
345+
className={twMerge(
346+
'group cursor-pointer select-none touch-none transition-colors duration-200 py-4',
347+
'flex w-full border-b-2 last:border-b-0 border-theme-border dark:border-dark-theme-border',
348+
selectedIndex === index
349+
? 'bg-theme-background-subtle dark:bg-dark-theme-background-subtle'
350+
: 'hover:bg-theme-background-subtle dark:hover:bg-dark-theme-background-subtle [@media(hover:none)]:hover:bg-transparent [@media(hover:none)]:dark:hover:bg-transparent',
351+
)}
352+
onClick={() => setSelectedIndex(selectedIndex === index ? undefined : index)}
353+
onContextMenu={e => {
354+
e.preventDefault();
355+
e.stopPropagation();
356+
setSelectedIndex(index);
357+
setIsTokenDetailsOpen(true);
358+
}}
359+
>
360+
<TokenListItem
361+
asset={asset}
362+
hasLoaded={!!transactions}
363+
tokens={wallet}
364+
tokenDetails={tokenDetails}
365+
total={portfolio?.total ?? 0}
366+
setIsTokenDetailsOpen={setIsTokenDetailsOpen}
367+
/>
368+
<TokenDetailsButton
369+
index={index}
370+
selectedIndex={selectedIndex}
371+
hasLoaded={!!transactions}
372+
isTokenDetailsOpen={isTokenDetailsOpen}
373+
tokens={wallet}
374+
tokenDetails={tokenDetails}
375+
total={portfolio?.total ?? 0}
376+
onSelectedIndexChange={setSelectedIndex}
377+
onTokenDetailsOpenChange={setIsTokenDetailsOpen}
378+
/>
379+
</div>
351380
))
352381
) : (
353382
<TokenListLoading />

0 commit comments

Comments
 (0)