Commit 5c9c8b4c authored by cartcrom's avatar cartcrom Committed by GitHub

feat: explore category info icons (#4787)

* added tooltips
* switched to premade tooltip component
* added 'help' cursor
parent 873d0ea2
...@@ -21,7 +21,6 @@ const ContractAddress = styled.button` ...@@ -21,7 +21,6 @@ const ContractAddress = styled.button`
border: none; border: none;
min-height: 38px; min-height: 38px;
padding: 0px; padding: 0px;
cursor: pointer;
` `
export default function AddressSection({ address }: { address: string }) { export default function AddressSection({ address }: { address: string }) {
......
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;
`
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 (
<span style={{ marginLeft: 4, display: 'flex', alignItems: 'center', backgroundColor: 'black' }}>
<Tooltip text={<InfoTipBody>{text}</InfoTipBody>} show={show} placement="right">
<InfoTipContainer onClick={open} onMouseEnter={open} onMouseLeave={close}>
<Info size={14} />
</InfoTipContainer>
</Tooltip>
</span>
)
}
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { TokenSortMethod } from 'graphql/data/TopTokens'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { textFadeIn } from 'theme/animations' import { textFadeIn } from 'theme/animations'
import { formatDollarAmount } from 'utils/formatDollarAmt' import { formatDollarAmount } from 'utils/formatDollarAmt'
import { HEADER_DESCRIPTIONS } from '../TokenTable/TokenRow'
import InfoTip from './InfoTip'
export const StatWrapper = styled.div` export const StatWrapper = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -24,6 +28,11 @@ export const StatPair = styled.div` ...@@ -24,6 +28,11 @@ export const StatPair = styled.div`
flex: 1; flex: 1;
flex-wrap: wrap; flex-wrap: wrap;
` `
const StatTitle = styled.div`
display: flex;
flex-direction: row;
gap: 4px;
`
const StatPrice = styled.span` const StatPrice = styled.span`
font-size: 28px; font-size: 28px;
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
...@@ -34,10 +43,14 @@ const NoData = styled.div` ...@@ -34,10 +43,14 @@ const NoData = styled.div`
type NumericStat = number | undefined | null type NumericStat = number | undefined | null
function Stat({ value, title }: { value: NumericStat; title: ReactNode }) { function Stat({ value, title, description }: { value: NumericStat; title: ReactNode; description?: ReactNode }) {
return ( return (
<StatWrapper> <StatWrapper>
{title} <StatTitle>
{title}
{description && <InfoTip text={description}></InfoTip>}
</StatTitle>
<StatPrice>{value ? formatDollarAmount(value) : '-'}</StatPrice> <StatPrice>{value ? formatDollarAmount(value) : '-'}</StatPrice>
</StatWrapper> </StatWrapper>
) )
...@@ -55,8 +68,20 @@ export default function StatsSection(props: StatsSectionProps) { ...@@ -55,8 +68,20 @@ export default function StatsSection(props: StatsSectionProps) {
return ( return (
<TokenStatsSection> <TokenStatsSection>
<StatPair> <StatPair>
<Stat value={TVL} title={<Trans>Total Value Locked</Trans>} /> <Stat
<Stat value={volume24H} title={<Trans>24H volume</Trans>} /> value={TVL}
description={HEADER_DESCRIPTIONS[TokenSortMethod.TOTAL_VALUE_LOCKED]}
title={<Trans>TVL</Trans>}
/>
<Stat
value={volume24H}
description={
<Trans>
24H volume is the amount of the asset that has been traded on Uniswap v3 during the past 24 hours.
</Trans>
}
title={<Trans>24H volume</Trans>}
/>
</StatPair> </StatPair>
<StatPair> <StatPair>
<Stat value={priceLow52W} title={<Trans>52W low</Trans>} /> <Stat value={priceLow52W} title={<Trans>52W low</Trans>} />
......
...@@ -13,6 +13,7 @@ import { ForwardedRef, forwardRef } from 'react' ...@@ -13,6 +13,7 @@ import { ForwardedRef, forwardRef } from 'react'
import { CSSProperties, ReactNode } from 'react' import { CSSProperties, ReactNode } from 'react'
import { ArrowDown, ArrowUp, Heart } from 'react-feather' import { ArrowDown, ArrowUp, Heart } from 'react-feather'
import { Link, useParams } from 'react-router-dom' import { Link, useParams } from 'react-router-dom'
import { Text } from 'rebass'
import styled, { css, useTheme } from 'styled-components/macro' import styled, { css, useTheme } from 'styled-components/macro'
import { ClickableStyle } from 'theme' import { ClickableStyle } from 'theme'
import { formatDollarAmount } from 'utils/formatDollarAmt' import { formatDollarAmount } from 'utils/formatDollarAmt'
...@@ -34,6 +35,7 @@ import { ...@@ -34,6 +35,7 @@ import {
useToggleFavorite, useToggleFavorite,
} from '../state' } from '../state'
import { useTokenLogoURI } from '../TokenDetails/ChartSection' import { useTokenLogoURI } from '../TokenDetails/ChartSection'
import InfoTip from '../TokenDetails/InfoTip'
import { formatDelta, getDeltaArrow } from '../TokenDetails/PriceChart' import { formatDelta, getDeltaArrow } from '../TokenDetails/PriceChart'
const Cell = styled.div` const Cell = styled.div`
...@@ -229,18 +231,18 @@ const PriceInfoCell = styled(Cell)` ...@@ -229,18 +231,18 @@ const PriceInfoCell = styled(Cell)`
align-items: flex-end; align-items: flex-end;
} }
` `
const SortArrowCell = styled(Cell)`
padding-right: 2px;
`
const HeaderCellWrapper = styled.span<{ onClick?: () => void }>` const HeaderCellWrapper = styled.span<{ onClick?: () => void }>`
align-items: center; align-items: center;
${ClickableStyle}
cursor: ${({ onClick }) => (onClick ? 'pointer' : 'unset')}; cursor: ${({ onClick }) => (onClick ? 'pointer' : 'unset')};
display: flex; display: flex;
gap: 4px;
height: 100%; height: 100%;
justify-content: flex-end; justify-content: flex-end;
width: 100%; width: 100%;
` `
const HeaderCellText = styled(Text)`
${ClickableStyle}
`
const SparkLineCell = styled(Cell)` const SparkLineCell = styled(Cell)`
padding: 0px 24px; padding: 0px 24px;
min-width: 120px; min-width: 120px;
...@@ -330,6 +332,17 @@ export const LogoContainer = styled.div` ...@@ -330,6 +332,17 @@ export const LogoContainer = styled.div`
display: flex; display: flex;
` `
export const HEADER_DESCRIPTIONS: Record<TokenSortMethod, ReactNode | undefined> = {
[TokenSortMethod.PRICE]: undefined,
[TokenSortMethod.PERCENT_CHANGE]: undefined,
[TokenSortMethod.TOTAL_VALUE_LOCKED]: (
<Trans>Total value locked (TVL) is the amount of the asset that’s currently in a Uniswap v3 liquidity pool.</Trans>
),
[TokenSortMethod.VOLUME]: (
<Trans>Volume is the amount of the asset that has been traded on Uniswap v3 during the selected time frame.</Trans>
),
}
/* Get singular header cell for header row */ /* Get singular header cell for header row */
function HeaderCell({ function HeaderCell({
category, category,
...@@ -343,31 +356,23 @@ function HeaderCell({ ...@@ -343,31 +356,23 @@ function HeaderCell({
const handleSortCategory = useSetSortMethod(category) const handleSortCategory = useSetSortMethod(category)
const sortMethod = useAtomValue(sortMethodAtom) const sortMethod = useAtomValue(sortMethodAtom)
if (sortMethod === category) { const description = HEADER_DESCRIPTIONS[category]
return (
<HeaderCellWrapper onClick={handleSortCategory}> return (
<SortArrowCell> <HeaderCellWrapper onClick={handleSortCategory}>
{sortMethod === category && (
<>
{sortAscending ? ( {sortAscending ? (
<ArrowUp size={20} strokeWidth={1.8} color={theme.accentActive} /> <ArrowUp size={20} strokeWidth={1.8} color={theme.accentActive} />
) : ( ) : (
<ArrowDown size={20} strokeWidth={1.8} color={theme.accentActive} /> <ArrowDown size={20} strokeWidth={1.8} color={theme.accentActive} />
)} )}
</SortArrowCell> </>
{category} )}
</HeaderCellWrapper> <HeaderCellText>{category}</HeaderCellText>
) {description && <InfoTip text={description}></InfoTip>}
} </HeaderCellWrapper>
if (sortable) { )
return (
<HeaderCellWrapper onClick={handleSortCategory}>
<SortArrowCell>
<ArrowUp size={14} visibility="hidden" />
</SortArrowCell>
{category}
</HeaderCellWrapper>
)
}
return <HeaderCellWrapper>{category}</HeaderCellWrapper>
} }
/* Token Row: skeleton row component */ /* Token Row: skeleton row component */
......
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