feat: [info] add new tdp nav (#7531)

* feat: [info] add new tdp nav

* tidy up code

* pr review

* nit remove unused component style

* pr review

* lol extraneous extra
This commit is contained in:
Kristie Huang 2023-11-09 14:51:23 -05:00 committed by GitHub
parent 712f82cb1a
commit 876d3a1cc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 31 deletions

@ -1,6 +1,7 @@
import { Trans } from '@lingui/macro'
import styled from 'styled-components'
import { CopyContractAddress, ThemedText } from 'theme/components'
import { shortenAddress } from 'utils/addresses'
const ContractAddressSection = styled.div`
display: flex;
@ -29,7 +30,7 @@ export default function AddressSection({ address }: { address: string }) {
<Trans>Contract address</Trans>
</ThemedText.SubHeaderSmall>
<ContractAddress>
<CopyContractAddress address={address} />
<CopyContractAddress address={address} truncatedAddress={shortenAddress(address, 2, 3)} />
</ContractAddress>
</ContractAddressSection>
)

@ -1,17 +1,31 @@
import { Link } from 'react-router-dom'
import styled from 'styled-components'
import styled, { css } from 'styled-components'
export const BreadcrumbNav = styled.div<{ isInfoTDPEnabled?: boolean }>`
display: flex;
color: ${({ theme }) => theme.neutral1};
${({ isInfoTDPEnabled }) =>
isInfoTDPEnabled
? css`
font-size: 16px;
line-height: 24px;
`
: css`
font-size: 14px;
line-height: 20px;
`}
align-items: center;
gap: 4px;
margin-bottom: 16px;
width: fit-content;
`
export const BreadcrumbNavLink = styled(Link)`
display: flex;
color: ${({ theme }) => theme.neutral2};
font-size: 14px;
line-height: 20px;
align-items: center;
gap: 4px;
text-decoration: none;
margin-bottom: 16px;
color: ${({ theme }) => theme.neutral2};
transition-duration: ${({ theme }) => theme.transition.duration.fast};
width: fit-content;
text-decoration: none;
&:hover {
color: ${({ theme }) => theme.neutral3};

@ -1,6 +1,8 @@
import { Trans } from '@lingui/macro'
import { SwapSkeleton } from 'components/swap/SwapSkeleton'
import { useInfoExplorePageEnabled } from 'featureFlags/flags/infoExplore'
import { ArrowLeft } from 'react-feather'
import { useInfoTDPEnabled } from 'featureFlags/flags/infoTDP'
import { ArrowLeft, ChevronRight } from 'react-feather'
import { useParams } from 'react-router-dom'
import styled, { useTheme } from 'styled-components'
import { ThemedText } from 'theme/components'
@ -8,7 +10,7 @@ import { textFadeIn } from 'theme/styles'
import { LoadingBubble } from '../loading'
import { AboutContainer, AboutHeader } from './About'
import { BreadcrumbNavLink } from './BreadcrumbNavLink'
import { BreadcrumbNav, BreadcrumbNavLink } from './BreadcrumbNavLink'
import { StatPair, StatsWrapper, StatWrapper } from './StatsSection'
const SWAP_COMPONENT_WIDTH = 360
@ -92,6 +94,9 @@ const SquaredBubble = styled(DetailBubble)`
height: 32px;
border-radius: 8px;
`
const NavBubble = styled(DetailBubble)`
width: 169px;
`
const TokenLogoBubble = styled(DetailBubble)`
width: 32px;
height: 32px;
@ -222,13 +227,26 @@ function LoadingStats() {
export default function TokenDetailsSkeleton() {
const { chainName } = useParams<{ chainName?: string }>()
const isInfoExplorePageEnabled = useInfoExplorePageEnabled()
const isInfoTDPEnabled = useInfoTDPEnabled()
return (
<LeftPanel>
{isInfoTDPEnabled ? (
<BreadcrumbNav isInfoTDPEnabled>
<BreadcrumbNavLink to={`${isInfoExplorePageEnabled ? '/explore' : ''}/tokens/${chainName}`}>
<Trans>Explore</Trans> <ChevronRight size={14} /> <Trans>Tokens</Trans> <ChevronRight size={14} />
</BreadcrumbNavLink>{' '}
<NavBubble />
</BreadcrumbNav>
) : (
<BreadcrumbNav>
<BreadcrumbNavLink
to={(isInfoExplorePageEnabled ? '/explore' : '') + (chainName ? `/tokens/${chainName}` : `/tokens`)}
>
<ArrowLeft size={14} /> Tokens
</BreadcrumbNavLink>
</BreadcrumbNav>
)}
<TokenInfoContainer>
<TokenNameCell>
<TokenLogoBubble />

@ -6,7 +6,7 @@ import { PortfolioLogo } from 'components/AccountDrawer/MiniPortfolio/PortfolioL
import { AboutSection } from 'components/Tokens/TokenDetails/About'
import AddressSection from 'components/Tokens/TokenDetails/AddressSection'
import BalanceSummary from 'components/Tokens/TokenDetails/BalanceSummary'
import { BreadcrumbNavLink } from 'components/Tokens/TokenDetails/BreadcrumbNavLink'
import { BreadcrumbNav, BreadcrumbNavLink } from 'components/Tokens/TokenDetails/BreadcrumbNavLink'
import ChartSection from 'components/Tokens/TokenDetails/ChartSection'
import MobileBalanceSummaryFooter from 'components/Tokens/TokenDetails/MobileBalanceSummaryFooter'
import ShareButton from 'components/Tokens/TokenDetails/ShareButton'
@ -32,12 +32,13 @@ import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch'
import { UNKNOWN_TOKEN_SYMBOL, useTokenFromActiveNetwork } from 'lib/hooks/useCurrency'
import { Swap } from 'pages/Swap'
import { useCallback, useMemo, useState, useTransition } from 'react'
import { ArrowLeft } from 'react-feather'
import { ArrowLeft, ChevronRight } from 'react-feather'
import { useNavigate } from 'react-router-dom'
import { Field } from 'state/swap/actions'
import { SwapState } from 'state/swap/reducer'
import styled from 'styled-components'
import { isAddress } from 'utils'
import { CopyContractAddress } from 'theme/components'
import { isAddress, shortenAddress } from 'utils'
import { addressesAreEquivalent } from 'utils/addressesAreEquivalent'
import { OnChangeTimePeriod } from './ChartSection'
@ -130,7 +131,6 @@ export default function TokenDetails({
}, {} as { [key: string]: string | undefined }) ?? {},
[tokenQueryData]
)
const isInfoTDPEnabled = useInfoTDPEnabled()
const { token: detailedToken, didFetchFromChain } = useRelevantToken(address, pageChainId, tokenQueryData)
@ -139,6 +139,7 @@ export default function TokenDetails({
const navigate = useNavigate()
const isInfoExplorePageEnabled = useInfoExplorePageEnabled()
const isInfoTDPEnabled = useInfoTDPEnabled()
// Wrapping navigate in a transition prevents Suspense from unnecessarily showing fallbacks again.
const [isPending, startTokenTransition] = useTransition()
@ -210,6 +211,7 @@ export default function TokenDetails({
if (detailedToken === undefined || !address) {
return <InvalidTokenDetails pageChainId={pageChainId} isInvalidAddress={!address} />
}
const tokenSymbolName = detailedToken && (detailedToken.symbol ?? <Trans>Symbol not found</Trans>)
return (
<Trace
page={InterfacePageName.TOKEN_DETAILS_PAGE}
@ -219,15 +221,37 @@ export default function TokenDetails({
<TokenDetailsLayout>
{detailedToken && !isPending ? (
<LeftPanel>
{isInfoTDPEnabled ? (
<BreadcrumbNav isInfoTDPEnabled>
<BreadcrumbNavLink to={`${isInfoExplorePageEnabled ? '/explore' : ''}/tokens/${chain.toLowerCase()}`}>
<Trans>Explore</Trans> <ChevronRight size={14} /> <Trans>Tokens</Trans> <ChevronRight size={14} />
</BreadcrumbNavLink>{' '}
{tokenSymbolName}{' '}
{!detailedToken.isNative && (
<>
(
<CopyContractAddress
address={address}
showTruncatedOnly
truncatedAddress={shortenAddress(address)}
/>
)
</>
)}
</BreadcrumbNav>
) : (
<BreadcrumbNav>
<BreadcrumbNavLink to={`${isInfoExplorePageEnabled ? '/explore' : ''}/tokens/${chain.toLowerCase()}`}>
<ArrowLeft data-testid="token-details-return-button" size={14} /> Tokens
</BreadcrumbNavLink>
</BreadcrumbNav>
)}
<TokenInfoContainer data-testid="token-info-container">
<TokenNameCell>
<PortfolioLogo currencies={[detailedToken]} chainId={detailedToken.chainId} size="32px" />
<TokenTitle>
{detailedToken.name ?? <Trans>Name not found</Trans>}
<TokenSymbol>{detailedToken.symbol ?? <Trans>Symbol not found</Trans>}</TokenSymbol>
<TokenSymbol>{tokenSymbolName}</TokenSymbol>
</TokenTitle>
</TokenNameCell>
<TokenActions>

@ -243,13 +243,14 @@ export function CopyLinkIcon({ toCopy }: { toCopy: string }) {
)
}
const FullAddress = styled.span`
const FullAddress = styled.span<{ showTruncated?: boolean }>`
${({ showTruncated }) => showTruncated && 'display: none;'}
@media only screen and (max-width: ${MOBILE_MEDIA_BREAKPOINT}) {
display: none;
}
`
const TruncatedAddress = styled.span`
display: none;
const TruncatedAddress = styled.span<{ showTruncated?: boolean }>`
display: ${({ showTruncated }) => (showTruncated ? 'flex' : 'none')};
@media only screen and (max-width: ${MOBILE_MEDIA_BREAKPOINT}) {
display: flex;
}
@ -273,7 +274,15 @@ const CopyContractAddressWrapper = styled.div`
display: flex;
`
export function CopyContractAddress({ address }: { address: string }) {
export function CopyContractAddress({
address,
showTruncatedOnly,
truncatedAddress,
}: {
address: string
showTruncatedOnly?: boolean
truncatedAddress?: string
}) {
const [isCopied, setCopied] = useCopyClipboard()
const [tooltipX, setTooltipX] = useState<number | undefined>()
const copy = useCallback(
@ -284,12 +293,11 @@ export function CopyContractAddress({ address }: { address: string }) {
[address, setCopied]
)
const truncated = `${address.slice(0, 4)}...${address.slice(-3)}`
return (
<CopyContractAddressWrapper onClick={copy}>
<CopyAddressRow isClicked={isCopied}>
<FullAddress>{address}</FullAddress>
<TruncatedAddress>{truncated}</TruncatedAddress>
<FullAddress showTruncated={showTruncatedOnly}>{address}</FullAddress>
<TruncatedAddress showTruncated={showTruncatedOnly}>{truncatedAddress}</TruncatedAddress>
<Copy size={14} />
</CopyAddressRow>
{isCopied && <Tooltip isCopyContractTooltip tooltipX={tooltipX} />}