-
Notifications
You must be signed in to change notification settings - Fork 13
feat/PRO-3225/new-token-tiles #290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
2e89e35
design implementation of new token tiles
RanaBug 3f2c20b
Merge branch 'staging' into feat/PRO-3225/new-token-tiles
RanaBug c786b68
minor fix
RanaBug e720cb0
fixes after review
RanaBug d98dd0e
rename file for TileTitle
RanaBug d865c4d
rename file for TileTitle
RanaBug b0ffb03
Merge branch 'staging' into feat/PRO-3225/new-token-tiles
RanaBug File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
461 changes: 36 additions & 425 deletions
461
...p/components/MediaGridCollection/tests/__snapshots__/DisplayCollectionImage.test.tsx.snap
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| import { useState } from 'react'; | ||
|
|
||
| // components | ||
| import Body from '../Typography/Body'; | ||
|
|
||
| type TileTitleProps = { | ||
| title?: string; | ||
| leftDecorator?: string; | ||
| rightDecorator?: string; | ||
| }; | ||
| const TileTitle = ({ | ||
| title, | ||
| leftDecorator, | ||
| rightDecorator, | ||
| }: TileTitleProps) => { | ||
| const [isBrokenImageRight, setIsBrokenImageRight] = useState<boolean>(false); | ||
| const [isBrokenImageLeft, setIsBrokenImageLeft] = useState<boolean>(false); | ||
|
|
||
| return ( | ||
| <div className="flex items-center gap-2"> | ||
| {leftDecorator && !isBrokenImageLeft && ( | ||
| <img | ||
| src={leftDecorator} | ||
| alt="left-decorator-image" | ||
| className="w-7 h-7 object-contain" | ||
| onError={() => setIsBrokenImageLeft(true)} | ||
| /> | ||
| )} | ||
| {title && <Body className="font-normal">{title}</Body>} | ||
| {rightDecorator && !isBrokenImageRight && ( | ||
| <img | ||
| src={rightDecorator} | ||
| alt="right-decorator-image" | ||
| className="w-6 h-6 object-fill rounded-full" | ||
| onError={() => setIsBrokenImageRight(true)} | ||
| /> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default TileTitle; |
90 changes: 90 additions & 0 deletions
90
src/apps/pillarx-app/components/TokenMarketDataRow/LeftColumnTokenMarketDataRow.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| /* eslint-disable jsx-a11y/no-noninteractive-element-interactions */ | ||
| import { formatDistanceToNowStrict, isValid, parseISO } from 'date-fns'; | ||
| import { DateTime } from 'luxon'; | ||
| import CopyToClipboard from 'react-copy-to-clipboard'; | ||
|
|
||
| // types | ||
| import { TokensMarketDataRow } from '../../../../types/api'; | ||
|
|
||
| // utils | ||
| import { getShorterTimeUnits } from '../../../../utils/common'; | ||
|
|
||
| // components | ||
| import Body from '../Typography/Body'; | ||
| import BodySmall from '../Typography/BodySmall'; | ||
|
|
||
| // images | ||
| import CopyIcon from '../../images/token-market-data-copy.png'; | ||
|
|
||
| type LeftColumnTokenMarketDataRowProps = { | ||
| data: TokensMarketDataRow; | ||
| }; | ||
|
|
||
| const LeftColumnTokenMarketDataRow = ({ | ||
| data, | ||
| }: LeftColumnTokenMarketDataRowProps) => { | ||
| const { leftColumn } = data; | ||
|
|
||
| const timestampToISO = | ||
| DateTime.fromSeconds(leftColumn?.line2?.timestamp || 0).toISO() || ''; | ||
|
|
||
| const ISOToDate = parseISO(timestampToISO); | ||
|
|
||
| let timestamp = isValid(ISOToDate) | ||
| ? formatDistanceToNowStrict( | ||
| DateTime.fromSeconds(leftColumn?.line2?.timestamp || 0).toISO() || '', | ||
| { addSuffix: true } | ||
| ) | ||
| : undefined; | ||
|
|
||
| // Replace long units with shorter units and delete white space before the units | ||
| timestamp = timestamp && getShorterTimeUnits(timestamp); | ||
|
|
||
| return ( | ||
| <div className="flex flex-col ml-1.5 h-full justify-between"> | ||
| <div className="flex gap-1 items-center"> | ||
| {leftColumn?.line1?.text1 && ( | ||
| <Body className="font-normal text-white desktop:text-base tablet:text-base mobile:text-sm"> | ||
| {leftColumn?.line1?.text1} | ||
| </Body> | ||
| )} | ||
| {leftColumn?.line1?.text2 && ( | ||
| <Body className="font-normal text-white/[.5] desktop:text-base tablet:text-base mobile:text-sm"> | ||
| {leftColumn?.line1?.text2} | ||
| </Body> | ||
| )} | ||
| {leftColumn?.line1?.copyLink && ( | ||
| <CopyToClipboard text={leftColumn.line1.copyLink}> | ||
| <img | ||
| src={CopyIcon} | ||
| alt="copy-token-address" | ||
| className="w-2.5 h-3" | ||
| onClick={(e) => e.stopPropagation()} | ||
| /> | ||
| </CopyToClipboard> | ||
| )} | ||
RanaBug marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| </div> | ||
| <div className="flex flex-wrap gap-2 mobile:gap-1.5"> | ||
| {timestamp && ( | ||
IAmKio marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| <BodySmall className="mobile:hidden text-white desktop:text-sm tablet:text-sm mobile:text-xs"> | ||
| {timestamp} | ||
| </BodySmall> | ||
| )} | ||
| {leftColumn?.line2?.volume && ( | ||
| <BodySmall className="text-white desktop:text-sm tablet:text-sm mobile:text-xs"> | ||
| <span className="text-white/[.5]">Vol:</span>{' '} | ||
| {leftColumn?.line2?.volume} | ||
| </BodySmall> | ||
| )} | ||
| {leftColumn?.line2?.liquidity && ( | ||
| <BodySmall className="text-white desktop:text-sm tablet:text-sm mobile:text-xs"> | ||
| <span className="text-white/[.5]">Liq:</span>{' '} | ||
| {leftColumn?.line2?.liquidity} | ||
| </BodySmall> | ||
| )} | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default LeftColumnTokenMarketDataRow; | ||
58 changes: 58 additions & 0 deletions
58
src/apps/pillarx-app/components/TokenMarketDataRow/RightColumnTokenMarketDataRow.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import { TbTriangleFilled } from 'react-icons/tb'; | ||
|
|
||
| // types | ||
| import { TokensMarketDataRow } from '../../../../types/api'; | ||
|
|
||
| // components | ||
| import Body from '../Typography/Body'; | ||
| import BodySmall from '../Typography/BodySmall'; | ||
|
|
||
| type RightColumnTokenMarketDataRowProps = { | ||
| data: TokensMarketDataRow; | ||
| }; | ||
|
|
||
| const RightColumnTokenMarketDataRow = ({ | ||
| data, | ||
| }: RightColumnTokenMarketDataRowProps) => { | ||
| const { rightColumn } = data; | ||
|
|
||
RanaBug marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| return ( | ||
| <div className="flex flex-col h-full items-end justify-between"> | ||
| <div className="flex desktop:gap-1 tablet:gap-1 mobile:flex-col mobile:items-end"> | ||
| {rightColumn?.line1?.price && ( | ||
| <Body | ||
| className={`font-normal ${rightColumn?.line1?.direction === 'UP' && 'desktop:text-market_row_green tablet:text-market_row_green'} ${rightColumn?.line1?.direction === 'DOWN' && 'desktop:text-percentage_red tablet:text-percentage_red'} mobile:text-white desktop:text-base tablet:text-base mobile:text-sm`} | ||
| > | ||
| {rightColumn?.line1?.price} | ||
| </Body> | ||
| )} | ||
| <div | ||
| className={`flex gap-1 items-center desktop:px-1 desktop:rounded tablet:px-1 tablet:rounded ${rightColumn?.line1?.direction === 'UP' && 'text-market_row_green desktop:bg-market_row_green/[.1] tablet:bg-market_row_green/[.1] mobile:bg-transparent'} ${rightColumn?.line1?.direction === 'DOWN' && 'text-percentage_red desktop:bg-percentage_red/[.1] tablet:bg-percentage_red/[.1] mobile:bg-transparent'}`} | ||
| > | ||
| {(rightColumn?.line1?.direction === 'UP' || | ||
| rightColumn?.line1?.direction === 'DOWN') && ( | ||
| <TbTriangleFilled | ||
| size={6} | ||
| color={ | ||
| rightColumn?.line1?.direction === 'UP' ? '#5CFF93' : '#FF366C' | ||
| } | ||
RanaBug marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /> | ||
| )} | ||
| {rightColumn?.line1?.percentage && ( | ||
| <BodySmall className="desktop:text-sm tablet:text-sm mobile:text-xs"> | ||
| {rightColumn?.line1?.percentage} | ||
| </BodySmall> | ||
| )} | ||
| </div> | ||
| </div> | ||
| {rightColumn?.line2?.transactionCount && ( | ||
| <BodySmall className="mobile:hidden text-white desktop:text-sm tablet:text-sm mobile:text-xs"> | ||
| <span className="text-white/[.5]">Txs:</span>{' '} | ||
| {rightColumn?.line2?.transactionCount} | ||
| </BodySmall> | ||
| )} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default RightColumnTokenMarketDataRow; | ||
58 changes: 58 additions & 0 deletions
58
src/apps/pillarx-app/components/TokenMarketDataRow/TokenLogoMarketDataRow.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| import { useState } from 'react'; | ||
|
|
||
| // components | ||
| import RandomAvatar from '../RandomAvatar/RandomAvatar'; | ||
|
|
||
| type TokenLogoMarketDataRowProps = { | ||
| tokenLogo?: string; | ||
| chainLogo?: string; | ||
| tokenName?: string; | ||
| }; | ||
|
|
||
| const TokenLogoMarketDataRow = ({ | ||
| tokenLogo, | ||
| chainLogo, | ||
| tokenName, | ||
| }: TokenLogoMarketDataRowProps) => { | ||
| const [isBrokenImage, setIsBrokenImage] = useState<boolean>(false); | ||
| const [isBrokenImageChain, setIsBrokenImageChain] = useState<boolean>(false); | ||
|
|
||
| return ( | ||
| <div className="relative w-10 h-10 mobile:w-9 mobile:h-9 rounded-full flex-shrink-0"> | ||
| {tokenLogo && !isBrokenImage ? ( | ||
| <img | ||
| src={tokenLogo} | ||
| alt="token-logo" | ||
| className="w-full h-full object-fill rounded-full" | ||
| data-testid="token-info-horizontal-logo" | ||
| onError={() => setIsBrokenImage(true)} | ||
| /> | ||
| ) : ( | ||
| <div className="w-full h-full overflow-hidden rounded-full"> | ||
| <RandomAvatar name={tokenName || ''} /> | ||
| </div> | ||
| )} | ||
|
|
||
| {/* Overlay text when no logo available */} | ||
| {(!tokenLogo || isBrokenImage) && ( | ||
| <span className="absolute inset-0 flex items-center justify-center text-white text-base font-normal"> | ||
| {tokenName?.slice(0, 2)} | ||
| </span> | ||
| )} | ||
|
|
||
| {/* Blockchain logo overlapping when only one blockchain for this token */} | ||
| {chainLogo && !isBrokenImageChain ? ( | ||
| <div className="absolute bottom-0 right-0 w-4 h-4 mobile:w-3 mobile:h-3 rounded-full overflow-hidden border-[1px] bg-white border-container_grey transform translate-x-1/5 translate-y-1/5"> | ||
| <img | ||
| src={chainLogo} | ||
| alt="logo" | ||
| className="w-full h-full object-contain" | ||
| onError={() => setIsBrokenImageChain(true)} | ||
| /> | ||
| </div> | ||
| ) : null} | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default TokenLogoMarketDataRow; |
51 changes: 51 additions & 0 deletions
51
src/apps/pillarx-app/components/TokenMarketDataRow/TokenMarketDataRow.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { useNavigate } from 'react-router-dom'; | ||
|
|
||
| // types | ||
| import { TokensMarketDataRow } from '../../../../types/api'; | ||
|
|
||
| // components | ||
| import Body from '../Typography/Body'; | ||
| import LeftColumnTokenMarketDataRow from './LeftColumnTokenMarketDataRow'; | ||
| import RightColumnTokenMarketDataRow from './RightColumnTokenMarketDataRow'; | ||
| import TokenLogoMarketDataRow from './TokenLogoMarketDataRow'; | ||
|
|
||
| type TokenMarketDataRowProps = { | ||
| data: TokensMarketDataRow; | ||
| listNumber: number; | ||
| isLastNumber: boolean; | ||
| isMiddleNumber: boolean; | ||
| }; | ||
| const TokenMarketDataRow = ({ | ||
| data, | ||
| listNumber, | ||
| isLastNumber, | ||
| isMiddleNumber, | ||
| }: TokenMarketDataRowProps) => { | ||
| const navigate = useNavigate(); | ||
| return ( | ||
| <div | ||
| className={`flex w-full h-full items-center justify-between gap-2 py-3 border-b-[1px] border-[#25232D] | ||
| ${isLastNumber && 'desktop:border-b-0 tablet:border-b-0 mobile:border-b-0'} | ||
| ${isMiddleNumber && 'desktop:border-b-0'} | ||
| ${data.link && 'cursor-pointer'}`} | ||
| onClick={() => (data.link ? navigate(`${data.link}`) : undefined)} | ||
| > | ||
| <div className="flex items-center flex-1 min-w-0"> | ||
| <Body className="desktop:text-base tablet:text-base mobile:text-sm font-normal text-white/[0.5] mr-4 mobile:mr-2.5"> | ||
| {listNumber > 0 && listNumber < 10 ? `0${listNumber}` : listNumber} | ||
| </Body> | ||
| <TokenLogoMarketDataRow | ||
| tokenLogo={data.leftColumn?.token?.primaryImage} | ||
| chainLogo={data.leftColumn?.token?.secondaryImage} | ||
| tokenName={data.leftColumn?.line1?.text2} | ||
| /> | ||
| <LeftColumnTokenMarketDataRow data={data} /> | ||
| </div> | ||
| <div className="flex-shrink-0"> | ||
| <RightColumnTokenMarketDataRow data={data} /> | ||
| </div> | ||
| </div> | ||
| ); | ||
| }; | ||
|
|
||
| export default TokenMarketDataRow; |
71 changes: 71 additions & 0 deletions
71
...pps/pillarx-app/components/TokenMarketDataRow/tests/LeftColumnTokenMarketDataRow.test.tsx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| import { render, screen } from '@testing-library/react'; | ||
|
|
||
| // components | ||
| import LeftColumnTokenMarketDataRow from '../LeftColumnTokenMarketDataRow'; | ||
|
|
||
| const ethTokenRow = { | ||
| link: 'token-atlas?someLink=true', | ||
| leftColumn: { | ||
| token: { | ||
| primaryImage: 'eth.png', | ||
| }, | ||
| line1: { | ||
| text1: 'ETH', | ||
| text2: 'Ethereum', | ||
| copyLink: '0xD76b5c2A23ef78368d8E34288B5b65D616B746aE', | ||
| }, | ||
| line2: { | ||
| timestamp: 1745331519, | ||
| volume: '1.2m', | ||
| liquidity: '$30,123', | ||
| }, | ||
| }, | ||
| rightColumn: { | ||
| line1: { | ||
| price: '$0.042188', | ||
| direction: 'UP', | ||
| percentage: '20.1%', | ||
| }, | ||
| line2: { | ||
| transactionCount: '1823', | ||
| }, | ||
| }, | ||
| }; | ||
|
|
||
| describe('<LeftColumnTokenMarketDataRow /> - ETH token row', () => { | ||
| it('renders and matches snapshot', () => { | ||
| const tree = render(<LeftColumnTokenMarketDataRow data={ethTokenRow} />); | ||
| expect(tree).toMatchSnapshot(); | ||
| }); | ||
|
|
||
| it('renders text1 and text2', () => { | ||
| render(<LeftColumnTokenMarketDataRow data={ethTokenRow} />); | ||
| expect(screen.getByText('ETH')).toBeInTheDocument(); | ||
| expect(screen.getByText('Ethereum')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('renders volume and liquidity', () => { | ||
| render(<LeftColumnTokenMarketDataRow data={ethTokenRow} />); | ||
| expect(screen.getByText(/Vol:/)).toBeInTheDocument(); | ||
| expect(screen.getByText('1.2m')).toBeInTheDocument(); | ||
| expect(screen.getByText(/Liq:/)).toBeInTheDocument(); | ||
| expect(screen.getByText('$30,123')).toBeInTheDocument(); | ||
| }); | ||
|
|
||
| it('does not break if some values are missing', () => { | ||
| const incomplete = { | ||
| leftColumn: { | ||
| line1: { | ||
| text1: 'ETH', | ||
| }, | ||
| line2: {}, | ||
| }, | ||
| }; | ||
|
|
||
| render(<LeftColumnTokenMarketDataRow data={incomplete} />); | ||
|
|
||
| expect(screen.getByText('ETH')).toBeInTheDocument(); | ||
| expect(screen.queryByText(/Vol:/)).not.toBeInTheDocument(); | ||
| expect(screen.queryByText(/Liq:/)).not.toBeInTheDocument(); | ||
| }); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.