diff --git a/src/components/Icons/ExplorerIcon.tsx b/src/components/Icons/ExplorerIcon.tsx new file mode 100644 index 0000000000..cc940e4217 --- /dev/null +++ b/src/components/Icons/ExplorerIcon.tsx @@ -0,0 +1,11 @@ +import { ComponentProps } from 'react' + +export const ExplorerIcon = (props: ComponentProps<'svg'>) => ( + + + +) diff --git a/src/pages/PoolDetails/PoolDetailsHeader.tsx b/src/pages/PoolDetails/PoolDetailsHeader.tsx index 81672bcc2a..57ec43f79a 100644 --- a/src/pages/PoolDetails/PoolDetailsHeader.tsx +++ b/src/pages/PoolDetails/PoolDetailsHeader.tsx @@ -125,7 +125,6 @@ const StyledLogoParentContainer = styled.div` top: 0; left: 0; ` - function DoubleCurrencyAndChainLogo({ chainId, currencies, @@ -165,37 +164,45 @@ function SquareL2Logo({ chainId }: { chainId: ChainId }) { ) } -function DoubleCurrencyLogo({ chainId, currencies }: { chainId: number; currencies: Array }) { +export function DoubleCurrencyLogo({ + chainId, + currencies, + small, +}: { + chainId: number + currencies: Array + small?: boolean +}) { const [src, nextSrc] = useTokenLogoSource(currencies?.[0]?.wrapped.address, chainId, currencies?.[0]?.isNative) const [src2, nextSrc2] = useTokenLogoSource(currencies?.[1]?.wrapped.address, chainId, currencies?.[1]?.isNative) - return + return } -const DoubleLogoContainer = styled.div` +const DoubleLogoContainer = styled.div<{ small?: boolean }>` display: flex; gap: 2px; position: relative; top: 0; left: 0; img { - width: 16px; - height: 32px; + width: ${({ small }) => (small ? '10px' : '16px')}; + height: ${({ small }) => (small ? '20px' : '32px')}; object-fit: cover; } img:first-child { - border-radius: 16px 0 0 16px; + border-radius: ${({ small }) => (small ? '10px 0 0 10px' : '16px 0 0 16px')}; object-position: 0 0; } img:last-child { - border-radius: 0 16px 16px 0; + border-radius: ${({ small }) => (small ? '0 10px 10px 0' : '0 16px 16px 0')}; object-position: 100% 0; } ` -const CircleLogoImage = styled.img` - width: 32px; - height: 32px; +const CircleLogoImage = styled.img<{ small?: boolean }>` + width: ${({ small }) => (small ? '10px' : '16px')}; + height: ${({ small }) => (small ? '20px' : '32px')}; border-radius: 50%; ` @@ -204,13 +211,14 @@ interface DoubleLogoProps { logo2?: string onError1?: () => void onError2?: () => void + small?: boolean } -function DoubleLogo({ logo1, onError1, logo2, onError2 }: DoubleLogoProps) { +function DoubleLogo({ logo1, onError1, logo2, onError2, small }: DoubleLogoProps) { return ( - - - + + + ) } diff --git a/src/pages/PoolDetails/PoolDetailsLink.test.tsx b/src/pages/PoolDetails/PoolDetailsLink.test.tsx new file mode 100644 index 0000000000..ba80690467 --- /dev/null +++ b/src/pages/PoolDetails/PoolDetailsLink.test.tsx @@ -0,0 +1,36 @@ +import { ChainId } from '@uniswap/sdk-core' +import { USDC_MAINNET } from 'constants/tokens' +import { usdcWethPoolAddress, validPoolToken0, validPoolToken1 } from 'test-utils/pools/fixtures' +import { render, screen } from 'test-utils/render' + +import { PoolDetailsLink } from './PoolDetailsLink' + +describe('PoolDetailsHeader', () => { + it('renders link for pool address', async () => { + const { asFragment } = render( + + ) + expect(asFragment()).toMatchSnapshot() + + expect(screen.getByText('USDC / WETH')).toBeInTheDocument() + expect(screen.getByTestId('pdp-pool-logo-USDC-WETH')).toBeInTheDocument() + expect(screen.getByTestId(`copy-address-${usdcWethPoolAddress}`)).toBeInTheDocument() + expect(screen.getByTestId(`explorer-url-https://etherscan.io/address/${usdcWethPoolAddress}`)).toBeInTheDocument() + }) + + it('renders link for token address', async () => { + const { asFragment } = render( + + ) + expect(asFragment()).toMatchSnapshot() + + expect(screen.getByText('USDC')).toBeInTheDocument() + expect(screen.getByTestId('pdp-token-logo-USDC')).toBeInTheDocument() + expect(screen.getByTestId(`copy-address-${USDC_MAINNET.address}`)).toBeInTheDocument() + expect(screen.getByTestId(`explorer-url-https://etherscan.io/token/${USDC_MAINNET.address}`)).toBeInTheDocument() + }) +}) diff --git a/src/pages/PoolDetails/PoolDetailsLink.tsx b/src/pages/PoolDetails/PoolDetailsLink.tsx new file mode 100644 index 0000000000..98caf5af2e --- /dev/null +++ b/src/pages/PoolDetails/PoolDetailsLink.tsx @@ -0,0 +1,165 @@ +import { Trans } from '@lingui/macro' +import { ChainId } from '@uniswap/sdk-core' +import { EtherscanLogo } from 'components/Icons/Etherscan' +import { ExplorerIcon } from 'components/Icons/ExplorerIcon' +import CurrencyLogo from 'components/Logo/CurrencyLogo' +import Row from 'components/Row' +import { useInfoExplorePageEnabled } from 'featureFlags/flags/infoExplore' +import { chainIdToBackendName, getTokenDetailsURL } from 'graphql/data/util' +import { Token } from 'graphql/thegraph/__generated__/types-and-hooks' +import { useCurrency } from 'hooks/Tokens' +import useCopyClipboard from 'hooks/useCopyClipboard' +import { useCallback } from 'react' +import { ChevronRight, Copy } from 'react-feather' +import { useNavigate } from 'react-router-dom' +import styled, { useTheme } from 'styled-components' +import { BREAKPOINTS } from 'theme' +import { ClickableStyle, EllipsisStyle, ExternalLink, ThemedText } from 'theme/components' +import { shortenAddress } from 'utils' +import { ExplorerDataType, getExplorerLink } from 'utils/getExplorerLink' + +import { DoubleCurrencyLogo } from './PoolDetailsHeader' +import { DetailBubble, SmallDetailBubble } from './shared' + +const TokenName = styled(ThemedText.BodyPrimary)` + display: none; + + @media (max-width: ${BREAKPOINTS.lg - 1}px) and (min-width: ${BREAKPOINTS.xs - 1}px) { + display: block; + } + ${EllipsisStyle} +` + +const TokenTextWrapper = styled(Row)<{ isClickable?: boolean }>` + gap: 8px; + margin-right: 12px; + ${({ isClickable }) => isClickable && ClickableStyle} +` + +const SymbolText = styled(ThemedText.BodyPrimary)` + flex-shrink: 0; + + @media (max-width: ${BREAKPOINTS.lg - 1}px) and (min-width: ${BREAKPOINTS.xs - 1}px) { + color: ${({ theme }) => theme.neutral2}; + } + ${EllipsisStyle} +` + +const CopyAddress = styled(Row)` + gap: 8px; + padding: 8px 12px; + border-radius: 20px; + background-color: ${({ theme }) => theme.surface3}; + font-size: 14px; + font-weight: 535; + line-height: 16px; + width: max-content; + flex-shrink: 0; + ${ClickableStyle} +` +const StyledCopyIcon = styled(Copy)` + width: 16px; + height: 16px; + color: ${({ theme }) => theme.neutral2}; + flex-shrink: 0; +` + +const ExplorerWrapper = styled.div` + padding: 8px; + border-radius: 20px; + background-color: ${({ theme }) => theme.surface3}; + display: flex; + ${ClickableStyle} +` + +const ButtonsRow = styled(Row)` + gap: 8px; + flex-shrink: 0; + width: max-content; +` + +interface PoolDetailsLinkProps { + address?: string + chainId?: number + tokens: (Token | undefined)[] + loading?: boolean +} + +export function PoolDetailsLink({ address, chainId, tokens, loading }: PoolDetailsLinkProps) { + const theme = useTheme() + const currencies = [ + useCurrency(tokens[0]?.id, chainId) ?? undefined, + useCurrency(tokens[1]?.id, chainId) ?? undefined, + ] + const [, setCopied] = useCopyClipboard() + const copy = useCallback(() => { + address && setCopied(address) + }, [address, setCopied]) + + const isPool = tokens.length === 2 + const explorerUrl = + address && chainId && getExplorerLink(chainId, address, isPool ? ExplorerDataType.ADDRESS : ExplorerDataType.TOKEN) + + const navigate = useNavigate() + const isInfoExplorePageEnabled = useInfoExplorePageEnabled() + const chainName = chainIdToBackendName(chainId) + const handleTokenTextClick = useCallback(() => { + if (!isPool) { + navigate(getTokenDetailsURL({ address: tokens[0]?.id, chain: chainName, isInfoExplorePageEnabled })) + } + }, [navigate, tokens, isPool, chainName, isInfoExplorePageEnabled]) + + if (loading || !address || !chainId) { + return ( + + + + + ) + } + + return ( + + + {isPool ? ( + + ) : ( + + )} + {isPool ? Pool : tokens[0]?.name} + + {isPool ? ( + `${tokens[0]?.symbol} / ${tokens[1]?.symbol}` + ) : ( + + {tokens[0]?.symbol} + + )} + + + + + {shortenAddress(address)} + + + {explorerUrl && ( + + + {chainId === ChainId.MAINNET ? ( + + ) : ( + + )} + + + )} + + + ) +} diff --git a/src/pages/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap b/src/pages/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap index 5f635c21f0..5e5466b9f3 100644 --- a/src/pages/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap +++ b/src/pages/PoolDetails/__snapshots__/PoolDetailsHeader.test.tsx.snap @@ -287,7 +287,7 @@ exports[`PoolDetailsHeader renders header text correctly 1`] = ` } .c12 { - width: 32px; + width: 16px; height: 32px; border-radius: 50%; } diff --git a/src/pages/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap b/src/pages/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap new file mode 100644 index 0000000000..259de24149 --- /dev/null +++ b/src/pages/PoolDetails/__snapshots__/PoolDetailsLink.test.tsx.snap @@ -0,0 +1,646 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PoolDetailsHeader renders link for pool address 1`] = ` + + .c0 { + box-sizing: border-box; + margin: 0; + min-width: 0; +} + +.c1 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: space-between; + -webkit-box-align: space-between; + -ms-flex-align: space-between; + align-items: space-between; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c6 { + color: #222222; +} + +.c12 { + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; + color: #FC72FF; + stroke: #FC72FF; + font-weight: 500; +} + +.c12:hover { + opacity: 0.6; +} + +.c12:active { + opacity: 0.4; +} + +.c4 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + gap: 2px; + position: relative; + top: 0; + left: 0; +} + +.c4 img { + width: 10px; + height: 20px; + object-fit: cover; +} + +.c4 img:first-child { + border-radius: 10px 0 0 10px; + object-position: 0 0; +} + +.c4 img:last-child { + border-radius: 0 10px 10px 0; + object-position: 100% 0; +} + +.c5 { + width: 10px; + height: 20px; + border-radius: 50%; +} + +.c7 { + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c3 { + gap: 8px; + margin-right: 12px; +} + +.c8 { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c10 { + gap: 8px; + padding: 8px 12px; + border-radius: 20px; + background-color: #22222212; + font-size: 14px; + font-weight: 535; + line-height: 16px; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c10:hover { + opacity: 0.6; +} + +.c10:active { + opacity: 0.4; +} + +.c11 { + width: 16px; + height: 16px; + color: #7D7D7D; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.c13 { + padding: 8px; + border-radius: 20px; + background-color: #22222212; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c13:hover { + opacity: 0.6; +} + +.c13:active { + opacity: 0.4; +} + +.c9 { + gap: 8px; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; +} + +@media (max-width:1023px) and (min-width:395px) { + .c7 { + display: block; + } +} + +@media (max-width:1023px) and (min-width:395px) { + .c8 { + color: #7D7D7D; + } +} + +
+
+
+ + +
+
+ Pool +
+
+ USDC / WETH +
+
+
+
+ 0x88e6...5640 + + + + +
+ +
+ + + + +
+
+
+
+
+`; + +exports[`PoolDetailsHeader renders link for token address 1`] = ` + + .c0 { + box-sizing: border-box; + margin: 0; + min-width: 0; +} + +.c1 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: space-between; + -webkit-box-align: space-between; + -ms-flex-align: space-between; + align-items: space-between; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c2 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c10 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + +.c7 { + color: #222222; +} + +.c14 { + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; + color: #FC72FF; + stroke: #FC72FF; + font-weight: 500; +} + +.c14:hover { + opacity: 0.6; +} + +.c14:active { + opacity: 0.4; +} + +.c6 { + opacity: 0; + -webkit-transition: opacity 250ms ease-in; + transition: opacity 250ms ease-in; + width: 20px; + height: 20px; + border-radius: 50%; +} + +.c5 { + width: 20px; + height: 20px; + background: #22222212; + -webkit-transition: background-color 250ms ease-in; + transition: background-color 250ms ease-in; + box-shadow: 0 0 1px white; + border-radius: 50%; +} + +.c4 { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + +.c8 { + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c3 { + gap: 8px; + margin-right: 12px; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c3:hover { + opacity: 0.6; +} + +.c3:active { + opacity: 0.4; +} + +.c9 { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c12 { + gap: 8px; + padding: 8px 12px; + border-radius: 20px; + background-color: #22222212; + font-size: 14px; + font-weight: 535; + line-height: 16px; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c12:hover { + opacity: 0.6; +} + +.c12:active { + opacity: 0.4; +} + +.c13 { + width: 16px; + height: 16px; + color: #7D7D7D; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.c15 { + padding: 8px; + border-radius: 20px; + background-color: #22222212; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c15:hover { + opacity: 0.6; +} + +.c15:active { + opacity: 0.4; +} + +.c11 { + gap: 8px; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; +} + +@media (max-width:1023px) and (min-width:395px) { + .c8 { + display: block; + } +} + +@media (max-width:1023px) and (min-width:395px) { + .c9 { + color: #7D7D7D; + } +} + +
+
+
+
+ UNKNOWN logo +
+
+
+ USD Coin +
+
+
+ USDC + + + +
+
+
+
+
+ 0xA0b8...eB48 + + + + +
+ +
+ + + + +
+
+
+
+
+`; diff --git a/src/pages/PoolDetails/__snapshots__/index.test.tsx.snap b/src/pages/PoolDetails/__snapshots__/index.test.tsx.snap index 810b5d7ffc..fe1ab05cf9 100644 --- a/src/pages/PoolDetails/__snapshots__/index.test.tsx.snap +++ b/src/pages/PoolDetails/__snapshots__/index.test.tsx.snap @@ -102,6 +102,41 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the padding: 4px 0px; } +.c58 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: space-between; + -webkit-box-align: space-between; + -ms-flex-align: space-between; + align-items: space-between; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; +} + +.c73 { + width: 100%; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + padding: 0; + -webkit-align-items: center; + -webkit-box-align: center; + -ms-flex-align: center; + align-items: center; + -webkit-box-pack: start; + -webkit-justify-content: flex-start; + -ms-flex-pack: start; + justify-content: flex-start; + gap: 4px; +} + .c8 { color: #7D7D7D; } @@ -110,6 +145,25 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the color: #222222; } +.c67 { + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; + color: #FC72FF; + stroke: #FC72FF; + font-weight: 500; +} + +.c67:hover { + opacity: 0.6; +} + +.c67:active { + opacity: 0.4; +} + .c3 { display: -webkit-box; display: -webkit-flex; @@ -230,6 +284,33 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the color: #FF5F52; } +.c72 { + opacity: 0; + -webkit-transition: opacity 250ms ease-in; + transition: opacity 250ms ease-in; + width: 20px; + height: 20px; + border-radius: 50%; +} + +.c71 { + width: 20px; + height: 20px; + background: #22222212; + -webkit-transition: background-color 250ms ease-in; + transition: background-color 250ms ease-in; + box-shadow: 0 0 1px white; + border-radius: 50%; +} + +.c70 { + position: relative; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; +} + .c18 { display: -webkit-box; display: -webkit-flex; @@ -383,12 +464,155 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the object-position: 100% 0; } +.c60 { + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + gap: 2px; + position: relative; + top: 0; + left: 0; +} + +.c60 img { + width: 10px; + height: 20px; + object-fit: cover; +} + +.c60 img:first-child { + border-radius: 10px 0 0 10px; + object-position: 0 0; +} + +.c60 img:last-child { + border-radius: 0 10px 10px 0; + object-position: 100% 0; +} + .c15 { - width: 32px; + width: 16px; height: 32px; border-radius: 50%; } +.c61 { + width: 10px; + height: 20px; + border-radius: 50%; +} + +.c62 { + display: none; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c59 { + gap: 8px; + margin-right: 12px; +} + +.c69 { + gap: 8px; + margin-right: 12px; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c69:hover { + opacity: 0.6; +} + +.c69:active { + opacity: 0.4; +} + +.c63 { + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.c65 { + gap: 8px; + padding: 8px 12px; + border-radius: 20px; + background-color: #22222212; + font-size: 14px; + font-weight: 535; + line-height: 16px; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c65:hover { + opacity: 0.6; +} + +.c65:active { + opacity: 0.4; +} + +.c66 { + width: 16px; + height: 16px; + color: #7D7D7D; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; +} + +.c68 { + padding: 8px; + border-radius: 20px; + background-color: #22222212; + display: -webkit-box; + display: -webkit-flex; + display: -ms-flexbox; + display: flex; + -webkit-text-decoration: none; + text-decoration: none; + cursor: pointer; + -webkit-transition-duration: 125ms; + transition-duration: 125ms; +} + +.c68:hover { + opacity: 0.6; +} + +.c68:active { + opacity: 0.4; +} + +.c64 { + gap: 8px; + -webkit-flex-shrink: 0; + -ms-flex-negative: 0; + flex-shrink: 0; + width: -webkit-max-content; + width: -moz-max-content; + width: max-content; +} + .c44 { font-weight: 485; font-size: 24px; @@ -629,6 +853,35 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the min-width: 360px; } +.c55 { + gap: 24px; + padding: 20px; +} + +.c56 { + width: 100%; + font-size: 24px; + font-weight: 485; + line-height: 32px; +} + +.c57 { + gap: 16px; + width: 100%; +} + +@media (max-width:1023px) and (min-width:395px) { + .c62 { + display: block; + } +} + +@media (max-width:1023px) and (min-width:395px) { + .c63 { + color: #7D7D7D; + } +} + @media (max-width:1023px) { .c44 { width: 100%; @@ -729,6 +982,24 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the } } +@media (max-width:1023px) and (min-width:640px) { + .c55 { + -webkit-flex-direction: row; + -ms-flex-direction: row; + flex-direction: row; + -webkit-flex-wrap: wrap; + -ms-flex-wrap: wrap; + flex-wrap: wrap; + padding: unset; + } +} + +@media (max-width:639px) { + .c55 { + padding: unset; + } +} +
@@ -1696,6 +1967,345 @@ exports[`PoolDetailsPage pool header is displayed when data is received from the
+
+
+ Links +
+
+
+
+
+ + +
+
+ Pool +
+
+ USDC / WETH +
+
+
+
+ 0x88e6...5640 + + + + +
+ +
+ + + + +
+
+
+
+
+
+
+
+ UNKNOWN logo +
+
+
+ USD Coin +
+
+
+ USDC + + + +
+
+
+
+
+ 0xA0b8...eB48 + + + + +
+ +
+ + + + +
+
+
+
+
+
+
+
+ WETH logo +
+
+
+ Wrapped Ether +
+
+
+ WETH + + + +
+
+
+
+
+ 0xC02a...6Cc2 + + + + +
+ +
+ + + + +
+
+
+
+
+
diff --git a/src/pages/PoolDetails/index.tsx b/src/pages/PoolDetails/index.tsx index 0babd3a6a9..e10b7f0971 100644 --- a/src/pages/PoolDetails/index.tsx +++ b/src/pages/PoolDetails/index.tsx @@ -1,3 +1,4 @@ +import { Trans } from '@lingui/macro' import Column from 'components/Column' import Row from 'components/Row' import { LoadingBubble } from 'components/Tokens/loading' @@ -7,15 +8,16 @@ import { usePoolData } from 'graphql/thegraph/PoolData' import NotFound from 'pages/NotFound' import { useReducer } from 'react' import { useParams } from 'react-router-dom' +import { Text } from 'rebass' import styled from 'styled-components' import { BREAKPOINTS } from 'theme' import { isAddress } from 'utils' import { PoolDetailsHeader } from './PoolDetailsHeader' +import { PoolDetailsLink } from './PoolDetailsLink' import { PoolDetailsStats } from './PoolDetailsStats' import { PoolDetailsStatsButtons } from './PoolDetailsStatsButtons' import { PoolDetailsTableSkeleton } from './PoolDetailsTableSkeleton' -import { DetailBubble, SmallDetailBubble } from './shared' const PageWrapper = styled(Row)` padding: 48px; @@ -55,11 +57,6 @@ const ChartHeaderBubble = styled(LoadingBubble)` height: 32px; ` -const LinkColumn = styled(Column)` - gap: 16px; - padding: 20px; -` - const RightColumn = styled(Column)` gap: 24px; margin: 0 48px 0 auto; @@ -73,6 +70,33 @@ const RightColumn = styled(Column)` } ` +const TokenDetailsWrapper = styled(Column)` + gap: 24px; + padding: 20px; + + @media (max-width: ${BREAKPOINTS.lg - 1}px) and (min-width: ${BREAKPOINTS.sm}px) { + flex-direction: row; + flex-wrap: wrap; + padding: unset; + } + + @media (max-width: ${BREAKPOINTS.sm - 1}px) { + padding: unset; + } +` + +const TokenDetailsHeader = styled(Text)` + width: 100%; + font-size: 24px; + font-weight: 485; + line-height: 32px; +` + +const LinksContainer = styled(Column)` + gap: 16px; + width: 100%; +` + export default function PoolDetailsPage() { const { poolAddress, chainName } = useParams<{ poolAddress: string @@ -116,19 +140,16 @@ export default function PoolDetailsPage() { loading={loading} /> - {(token0 || token1 || loading) && - (loading ? ( - - - {Array.from({ length: 3 }).map((_, i) => ( - - - - - ))} - - ) : null)} - {/* TODO(WEB-2985) replace with new Token Links component */} + + + Links + + + + + + + ) diff --git a/src/test-utils/pools/fixtures.ts b/src/test-utils/pools/fixtures.ts index de6cef2727..ffdc8bc68d 100644 --- a/src/test-utils/pools/fixtures.ts +++ b/src/test-utils/pools/fixtures.ts @@ -89,9 +89,11 @@ export const useMultiChainPositionsReturnValue = { loading: false, } +export const usdcWethPoolAddress = '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640' + export const validPoolDataResponse = { data: { - id: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640', + id: usdcWethPoolAddress, feeTier: 500, liquidity: parseFloat('26414803986874770777'), sqrtPrice: parseFloat('1977320351696380862605029898750440'), @@ -108,7 +110,7 @@ export const validPoolDataResponse = { totalValueLockedToken1: '130641.89297715763283183', totalValueLockedUSD: '399590762.8476702153638342035105795', __typename: 'Pool', - address: '0x88e6a0c2ddd26feeb64f039a2c41296fcb3f5640', + address: usdcWethPoolAddress, volumeUSDChange: -17.753809465717136, volumeUSDWeek: 1359911419.265625, tvlUSD: 223166198.4690675,