Commit 4442933e authored by cartcrom's avatar cartcrom Committed by GitHub

feat: fetch top tokens based on volume & update data descriptions (#5360)

* replaced info icons w/ popover text
* replaced tooltip components w/ existing mouseover component
* fix: updating useCallback dependencies in tooltip component
* fix: removing redundant space
parent 8447b303
import Tooltip from 'components/Tooltip'
import { ReactNode, useCallback, useState } from 'react'
import { Info } from 'react-feather'
import styled from 'styled-components/macro'
const InfoTipContainer = styled.div`
display: flex;
position: relative;
align-items: center;
cursor: help;
`
const InfoTipBody = styled.div`
color: ${({ theme }) => theme.textPrimary};
font-weight: 400;
font-size: 12px;
line-height: 16px;
`
const InfoTipWrapper = styled.div`
margin-left: 4px;
display: flex;
align-items: center;
`
export default function InfoTip({ text }: { text: ReactNode; size?: number }) {
const [show, setShow] = useState<boolean>(false)
const open = useCallback(() => setShow(true), [setShow])
const close = useCallback(() => setShow(false), [setShow])
return (
<InfoTipWrapper>
<Tooltip text={<InfoTipBody>{text}</InfoTipBody>} show={show} placement="right">
<InfoTipContainer onClick={open} onMouseEnter={open} onMouseLeave={close}>
<Info size={14} />
</InfoTipContainer>
</Tooltip>
</InfoTipWrapper>
)
}
import { Trans } from '@lingui/macro'
import { formatNumber, NumberType } from '@uniswap/conedison/format'
import { MouseoverTooltip } from 'components/Tooltip'
import { ReactNode } from 'react'
import styled from 'styled-components/macro'
import { ThemedText } from 'theme'
......@@ -7,16 +8,12 @@ import { textFadeIn } from 'theme/styles'
import { TokenSortMethod } from '../state'
import { HEADER_DESCRIPTIONS } from '../TokenTable/TokenRow'
import InfoTip from './InfoTip'
export const StatWrapper = styled.div`
display: flex;
flex-direction: column;
color: ${({ theme }) => theme.textSecondary};
font-size: 14px;
min-width: 168px;
flex: 1;
gap: 4px;
padding: 24px 0px;
`
const TokenStatsSection = styled.div`
......@@ -32,12 +29,9 @@ export const StatPair = styled.div`
const Header = styled(ThemedText.MediumHeader)`
font-size: 28px !important;
`
const StatTitle = styled.div`
display: flex;
flex-direction: row;
gap: 4px;
`
const StatPrice = styled.span`
const StatPrice = styled.div`
margin-top: 4px;
font-size: 28px;
color: ${({ theme }) => theme.textPrimary};
`
......@@ -54,10 +48,7 @@ type NumericStat = number | undefined | null
function Stat({ value, title, description }: { value: NumericStat; title: ReactNode; description?: ReactNode }) {
return (
<StatWrapper>
<StatTitle>
{title}
{description && <InfoTip text={description}></InfoTip>}
</StatTitle>
<MouseoverTooltip text={description}>{title}</MouseoverTooltip>
<StatPrice>{formatNumber(value, NumberType.FiatTokenStats)}</StatPrice>
</StatWrapper>
)
......
......@@ -5,13 +5,14 @@ import { formatNumber, formatUSDPrice, NumberType } from '@uniswap/conedison/for
import { ParentSize } from '@visx/responsive'
import SparklineChart from 'components/Charts/SparklineChart'
import QueryTokenLogo from 'components/Logo/QueryTokenLogo'
import { MouseoverTooltip } from 'components/Tooltip'
import { getChainInfo } from 'constants/chainInfo'
import { SparklineMap, TopToken } from 'graphql/data/TopTokens'
import { CHAIN_NAME_TO_CHAIN_ID, getTokenDetailsURL } from 'graphql/data/util'
import { useAtomValue } from 'jotai/utils'
import { ForwardedRef, forwardRef } from 'react'
import { CSSProperties, ReactNode } from 'react'
import { ArrowDown, ArrowUp } from 'react-feather'
import { ArrowDown, ArrowUp, Info } from 'react-feather'
import { Link, useParams } from 'react-router-dom'
import styled, { css, useTheme } from 'styled-components/macro'
import { ClickableStyle } from 'theme'
......@@ -31,7 +32,6 @@ import {
TokenSortMethod,
useSetSortMethod,
} from '../state'
import InfoTip from '../TokenDetails/InfoTip'
import { ArrowCell, DeltaText, formatDelta, getDeltaArrow } from '../TokenDetails/PriceChart'
const Cell = styled.div`
......@@ -200,7 +200,6 @@ const HeaderCellWrapper = styled.span<{ onClick?: () => void }>`
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'unset')};
display: flex;
gap: 4px;
height: 100%;
justify-content: flex-end;
width: 100%;
......@@ -297,6 +296,13 @@ export const LogoContainer = styled.div`
display: flex;
`
const InfoIconContainer = styled.div`
margin-left: 2px;
display: flex;
align-items: center;
cursor: help;
`
export const HEADER_DESCRIPTIONS: Record<TokenSortMethod, ReactNode | undefined> = {
[TokenSortMethod.PRICE]: undefined,
[TokenSortMethod.PERCENT_CHANGE]: undefined,
......@@ -333,7 +339,13 @@ function HeaderCell({
</>
)}
{category}
{description && <InfoTip text={description}></InfoTip>}
{description && (
<MouseoverTooltip text={description} placement="right">
<InfoIconContainer>
<Info size={14} />
</InfoIconContainer>
</MouseoverTooltip>
)}
</HeaderCellWrapper>
)
}
......
......@@ -8,7 +8,11 @@ export const TooltipContainer = styled.div`
max-width: 256px;
cursor: default;
padding: 0.6rem 1rem;
color: ${({ theme }) => theme.textPrimary};
font-weight: 400;
font-size: 12px;
line-height: 16px;
word-break: break-word;
background: ${({ theme }) => theme.backgroundSurface};
......@@ -56,7 +60,7 @@ function TooltipContent({ content, wrap = false, ...rest }: TooltipContentProps)
/** Standard text tooltip. */
export function MouseoverTooltip({ text, disableHover, children, timeout, ...rest }: Omit<TooltipProps, 'show'>) {
const [show, setShow] = useState(false)
const open = useCallback(() => setShow(true), [setShow])
const open = useCallback(() => text && setShow(true), [text, setShow])
const close = useCallback(() => setShow(false), [setShow])
useEffect(() => {
......
......@@ -19,7 +19,7 @@ import { CHAIN_NAME_TO_CHAIN_ID, isPricePoint, PricePoint, toHistoryDuration, un
gql`
query TopTokens100($duration: HistoryDuration!, $chain: Chain!) {
topTokens(pageSize: 100, page: 1, chain: $chain) {
topTokens(pageSize: 100, page: 1, chain: $chain, orderBy: VOLUME) {
id
name
chain
......
......@@ -8,6 +8,7 @@ import NetworkFilter from 'components/Tokens/TokenTable/NetworkFilter'
import SearchBar from 'components/Tokens/TokenTable/SearchBar'
import TimeSelector from 'components/Tokens/TokenTable/TimeSelector'
import TokenTable from 'components/Tokens/TokenTable/TokenTable'
import { MouseoverTooltip } from 'components/Tooltip'
import { chainIdToBackendName, isValidBackendChainName } from 'graphql/data/util'
import { useOnGlobalChainSwitch } from 'hooks/useGlobalChainSwitch'
import { useResetAtom } from 'jotai/utils'
......@@ -46,8 +47,8 @@ const FiltersContainer = styled.div`
}
`
const SearchContainer = styled(FiltersContainer)`
width: 100%;
margin-left: 8px;
width: 100%;
@media only screen and (max-width: ${MEDIUM_MEDIA_BREAKPOINT}) {
margin: 0px;
......@@ -59,6 +60,8 @@ const FiltersWrapper = styled.div`
max-width: ${MAX_WIDTH_MEDIA_BREAKPOINT};
margin: 0 auto;
margin-bottom: 20px;
color: ${({ theme }) => theme.textTertiary};
flex-direction: row;
@media only screen and (max-width: ${MEDIUM_MEDIA_BREAKPOINT}) {
flex-direction: column;
......@@ -94,9 +97,14 @@ const Tokens = () => {
<Trace page={PageName.TOKENS_PAGE} shouldLogImpression>
<ExploreContainer>
<TitleContainer>
<MouseoverTooltip
text={<Trans>This table contains the top tokens by Uniswap volume, sorted based on your input.</Trans>}
placement="bottom"
>
<ThemedText.LargeHeader>
<Trans>Top tokens on Uniswap</Trans>
</ThemedText.LargeHeader>
</MouseoverTooltip>
</TitleContainer>
<FiltersWrapper>
<FiltersContainer>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment