chore(cleanup): separate the components for 3 kinds of links we use
This commit is contained in:
parent
98d25dd2af
commit
e2d0514344
@ -2,10 +2,10 @@ import React from 'react'
|
|||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import useCopyClipboard from '../../hooks/useCopyClipboard'
|
import useCopyClipboard from '../../hooks/useCopyClipboard'
|
||||||
|
|
||||||
import { Link } from '../../theme'
|
import { LinkStyledButton } from '../../theme'
|
||||||
import { CheckCircle, Copy } from 'react-feather'
|
import { CheckCircle, Copy } from 'react-feather'
|
||||||
|
|
||||||
const CopyIcon = styled(Link)`
|
const CopyIcon = styled(LinkStyledButton)`
|
||||||
color: ${({ theme }) => theme.text4};
|
color: ${({ theme }) => theme.text4};
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -4,7 +4,7 @@ import { Check, Triangle } from 'react-feather'
|
|||||||
|
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { getEtherscanLink } from '../../utils'
|
import { getEtherscanLink } from '../../utils'
|
||||||
import { Link, Spinner } from '../../theme'
|
import { ExternalLink, Spinner } from '../../theme'
|
||||||
import Circle from '../../assets/images/circle.svg'
|
import Circle from '../../assets/images/circle.svg'
|
||||||
|
|
||||||
import { transparentize } from 'polished'
|
import { transparentize } from 'polished'
|
||||||
@ -18,7 +18,7 @@ const TransactionStatusText = styled.div`
|
|||||||
margin-right: 0.5rem;
|
margin-right: 0.5rem;
|
||||||
`
|
`
|
||||||
|
|
||||||
const TransactionState = styled(Link)<{ pending: boolean; success?: boolean }>`
|
const TransactionState = styled(ExternalLink)<{ pending: boolean; success?: boolean }>`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
text-decoration: none !important;
|
text-decoration: none !important;
|
||||||
|
@ -21,7 +21,7 @@ import Identicon from '../Identicon'
|
|||||||
|
|
||||||
import { ButtonEmpty } from '../Button'
|
import { ButtonEmpty } from '../Button'
|
||||||
|
|
||||||
import { Link, TYPE } from '../../theme'
|
import { ExternalLink, LinkStyledButton, TYPE } from '../../theme'
|
||||||
|
|
||||||
const HeaderRow = styled.div`
|
const HeaderRow = styled.div`
|
||||||
${({ theme }) => theme.flexRowNoWrap};
|
${({ theme }) => theme.flexRowNoWrap};
|
||||||
@ -160,7 +160,7 @@ const ConnectButtonRow = styled.div`
|
|||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
`
|
`
|
||||||
|
|
||||||
const StyledLink = styled(Link)<{ hasENS: boolean; isENS: boolean }>`
|
const AddressLink = styled(ExternalLink)<{ hasENS: boolean; isENS: boolean }>`
|
||||||
color: ${({ hasENS, isENS, theme }) => (hasENS ? (isENS ? theme.primary1 : theme.text3) : theme.primary1)};
|
color: ${({ hasENS, isENS, theme }) => (hasENS ? (isENS ? theme.primary1 : theme.text3) : theme.primary1)};
|
||||||
`
|
`
|
||||||
|
|
||||||
@ -357,17 +357,21 @@ export default function AccountDetails({
|
|||||||
{ENSName ? (
|
{ENSName ? (
|
||||||
<>
|
<>
|
||||||
<AccountControl hasENS={!!ENSName} isENS={false}>
|
<AccountControl hasENS={!!ENSName} isENS={false}>
|
||||||
<StyledLink hasENS={!!ENSName} isENS={true} href={getEtherscanLink(chainId, ENSName, 'address')}>
|
<AddressLink hasENS={!!ENSName} isENS={true} href={getEtherscanLink(chainId, ENSName, 'address')}>
|
||||||
View on Etherscan ↗
|
View on Etherscan ↗
|
||||||
</StyledLink>
|
</AddressLink>
|
||||||
</AccountControl>
|
</AccountControl>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<>
|
||||||
<AccountControl hasENS={!!ENSName} isENS={false}>
|
<AccountControl hasENS={!!ENSName} isENS={false}>
|
||||||
<StyledLink hasENS={!!ENSName} isENS={false} href={getEtherscanLink(chainId, account, 'address')}>
|
<AddressLink
|
||||||
|
hasENS={!!ENSName}
|
||||||
|
isENS={false}
|
||||||
|
href={getEtherscanLink(chainId, account, 'address')}
|
||||||
|
>
|
||||||
View on Etherscan ↗
|
View on Etherscan ↗
|
||||||
</StyledLink>
|
</AddressLink>
|
||||||
</AccountControl>
|
</AccountControl>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@ -395,7 +399,7 @@ export default function AccountDetails({
|
|||||||
<LowerSection>
|
<LowerSection>
|
||||||
<AutoRow style={{ justifyContent: 'space-between' }}>
|
<AutoRow style={{ justifyContent: 'space-between' }}>
|
||||||
<TYPE.body>Recent Transactions</TYPE.body>
|
<TYPE.body>Recent Transactions</TYPE.body>
|
||||||
<Link onClick={clearAllTransactionsCallback}>(clear all)</Link>
|
<LinkStyledButton onClick={clearAllTransactionsCallback}>(clear all)</LinkStyledButton>
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
{renderTransactions(pendingTransactions)}
|
{renderTransactions(pendingTransactions)}
|
||||||
{renderTransactions(confirmedTransactions)}
|
{renderTransactions(confirmedTransactions)}
|
||||||
|
@ -4,7 +4,7 @@ import useDebounce from '../../hooks/useDebounce'
|
|||||||
|
|
||||||
import { isAddress } from '../../utils'
|
import { isAddress } from '../../utils'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { Link, TYPE } from '../../theme'
|
import { ExternalLink, TYPE } from '../../theme'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
import { getEtherscanLink } from '../../utils'
|
import { getEtherscanLink } from '../../utils'
|
||||||
@ -160,12 +160,12 @@ export default function AddressInputPanel({
|
|||||||
Recipient
|
Recipient
|
||||||
</TYPE.black>
|
</TYPE.black>
|
||||||
{data.address && (
|
{data.address && (
|
||||||
<Link
|
<ExternalLink
|
||||||
href={getEtherscanLink(chainId, data.name || data.address, 'address')}
|
href={getEtherscanLink(chainId, data.name || data.address, 'address')}
|
||||||
style={{ fontSize: '14px' }}
|
style={{ fontSize: '14px' }}
|
||||||
>
|
>
|
||||||
(View on Etherscan)
|
(View on Etherscan)
|
||||||
</Link>
|
</ExternalLink>
|
||||||
)}
|
)}
|
||||||
</RowBetween>
|
</RowBetween>
|
||||||
<Input
|
<Input
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import React, { useCallback, useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
import { RouteComponentProps, withRouter } from 'react-router-dom'
|
|
||||||
|
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
import Loader from '../Loader'
|
import Loader from '../Loader'
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { CloseIcon } from '../../theme/components'
|
import { CloseIcon } from '../../theme/components'
|
||||||
import { RowBetween } from '../Row'
|
import { RowBetween } from '../Row'
|
||||||
@ -32,7 +30,7 @@ const ConfirmedIcon = styled(ColumnCenter)`
|
|||||||
padding: 60px 0;
|
padding: 60px 0;
|
||||||
`
|
`
|
||||||
|
|
||||||
interface ConfirmationModalProps extends RouteComponentProps<{}> {
|
interface ConfirmationModalProps {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
onDismiss: () => void
|
onDismiss: () => void
|
||||||
hash: string
|
hash: string
|
||||||
@ -44,8 +42,7 @@ interface ConfirmationModalProps extends RouteComponentProps<{}> {
|
|||||||
title?: string
|
title?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
function ConfirmationModal({
|
export default function ConfirmationModal({
|
||||||
history,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
onDismiss,
|
onDismiss,
|
||||||
hash,
|
hash,
|
||||||
@ -59,13 +56,6 @@ function ConfirmationModal({
|
|||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
const theme = useContext(ThemeContext)
|
const theme = useContext(ThemeContext)
|
||||||
|
|
||||||
const dismissAndReturn = useCallback(() => {
|
|
||||||
if (history.location.pathname.match('/add') || history.location.pathname.match('/remove')) {
|
|
||||||
history.push('/pool')
|
|
||||||
}
|
|
||||||
onDismiss()
|
|
||||||
}, [onDismiss, history])
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}>
|
<Modal isOpen={isOpen} onDismiss={onDismiss} maxHeight={90}>
|
||||||
{!attemptingTxn ? (
|
{!attemptingTxn ? (
|
||||||
@ -106,12 +96,12 @@ function ConfirmationModal({
|
|||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
{!pendingConfirmation && (
|
{!pendingConfirmation && (
|
||||||
<>
|
<>
|
||||||
<Link href={getEtherscanLink(chainId, hash, 'transaction')}>
|
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>
|
||||||
<Text fontWeight={500} fontSize={14} color={theme.primary1}>
|
<Text fontWeight={500} fontSize={14} color={theme.primary1}>
|
||||||
View on Etherscan
|
View on Etherscan
|
||||||
</Text>
|
</Text>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
<ButtonPrimary onClick={dismissAndReturn} style={{ margin: '20px 0 0 0' }}>
|
<ButtonPrimary onClick={onDismiss} style={{ margin: '20px 0 0 0' }}>
|
||||||
<Text fontWeight={500} fontSize={20}>
|
<Text fontWeight={500} fontSize={20}>
|
||||||
Close
|
Close
|
||||||
</Text>
|
</Text>
|
||||||
@ -131,5 +121,3 @@ function ConfirmationModal({
|
|||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default withRouter(ConfirmationModal)
|
|
||||||
|
@ -8,7 +8,7 @@ import Row from '../Row'
|
|||||||
import Menu from '../Menu'
|
import Menu from '../Menu'
|
||||||
import Web3Status from '../Web3Status'
|
import Web3Status from '../Web3Status'
|
||||||
|
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { WETH, ChainId } from '@uniswap/sdk'
|
import { WETH, ChainId } from '@uniswap/sdk'
|
||||||
import { isMobile } from 'react-device-detect'
|
import { isMobile } from 'react-device-detect'
|
||||||
@ -159,13 +159,13 @@ export default function Header() {
|
|||||||
<HeaderFrame>
|
<HeaderFrame>
|
||||||
<MigrateBanner>
|
<MigrateBanner>
|
||||||
Uniswap V2 is live! Read the
|
Uniswap V2 is live! Read the
|
||||||
<Link href="https://uniswap.org/blog/launch-uniswap-v2/">
|
<ExternalLink href="https://uniswap.org/blog/launch-uniswap-v2/">
|
||||||
<b>blog post ↗</b>
|
<b>blog post ↗</b>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
or
|
or
|
||||||
<Link href="https://migrate.uniswap.exchange/">
|
<ExternalLink href="https://migrate.uniswap.exchange/">
|
||||||
<b>migrate your liquidity ↗</b>
|
<b>migrate your liquidity ↗</b>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
.
|
.
|
||||||
</MigrateBanner>
|
</MigrateBanner>
|
||||||
<RowBetween padding="1rem">
|
<RowBetween padding="1rem">
|
||||||
|
@ -4,7 +4,7 @@ import styled from 'styled-components'
|
|||||||
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
|
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
|
||||||
import useToggle from '../../hooks/useToggle'
|
import useToggle from '../../hooks/useToggle'
|
||||||
|
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
|
|
||||||
const StyledMenuIcon = styled(MenuIcon)`
|
const StyledMenuIcon = styled(MenuIcon)`
|
||||||
path {
|
path {
|
||||||
@ -63,7 +63,7 @@ const MenuFlyout = styled.span`
|
|||||||
z-index: 100;
|
z-index: 100;
|
||||||
`
|
`
|
||||||
|
|
||||||
const MenuItem = styled(Link)`
|
const MenuItem = styled(ExternalLink)`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0.5rem 0.5rem;
|
padding: 0.5rem 0.5rem;
|
||||||
color: ${({ theme }) => theme.text2};
|
color: ${({ theme }) => theme.text2};
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
import React, { useContext } from 'react'
|
import { ChainId, Pair, Token } from '@uniswap/sdk'
|
||||||
|
import React, { useContext, useMemo } from 'react'
|
||||||
import styled, { ThemeContext } from 'styled-components'
|
import styled, { ThemeContext } from 'styled-components'
|
||||||
import { useMediaLayout } from 'use-media'
|
import { useMediaLayout } from 'use-media'
|
||||||
|
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
import { PopupContent } from '../../state/application/actions'
|
import { PopupContent } from '../../state/application/actions'
|
||||||
import { useActivePopups, useRemovePopup } from '../../state/application/hooks'
|
import { useActivePopups, useRemovePopup } from '../../state/application/hooks'
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import DoubleTokenLogo from '../DoubleLogo'
|
import DoubleTokenLogo from '../DoubleLogo'
|
||||||
import Row from '../Row'
|
import Row from '../Row'
|
||||||
@ -71,6 +72,40 @@ const Popup = styled.div`
|
|||||||
`}
|
`}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
function PoolPopup({
|
||||||
|
token0,
|
||||||
|
token1
|
||||||
|
}: {
|
||||||
|
token0: { address?: string; symbol?: string }
|
||||||
|
token1: { address?: string; symbol?: string }
|
||||||
|
}) {
|
||||||
|
const pairAddress: string | null = useMemo(() => {
|
||||||
|
if (!token0 || !token1) return null
|
||||||
|
// just mock it out
|
||||||
|
return Pair.getAddress(
|
||||||
|
new Token(ChainId.MAINNET, token0.address, 18),
|
||||||
|
new Token(ChainId.MAINNET, token1.address, 18)
|
||||||
|
)
|
||||||
|
}, [token0, token1])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AutoColumn gap={'10px'}>
|
||||||
|
<Text fontSize={20} fontWeight={500}>
|
||||||
|
Pool Imported
|
||||||
|
</Text>
|
||||||
|
<Row>
|
||||||
|
<DoubleTokenLogo a0={token0?.address ?? ''} a1={token1?.address ?? ''} margin={true} />
|
||||||
|
<Text fontSize={16} fontWeight={500}>
|
||||||
|
UNI {token0?.symbol} / {token1?.symbol}
|
||||||
|
</Text>
|
||||||
|
</Row>
|
||||||
|
{pairAddress ? (
|
||||||
|
<ExternalLink href={`https://uniswap.info/pair/${pairAddress}`}>View on Uniswap Info.</ExternalLink>
|
||||||
|
) : null}
|
||||||
|
</AutoColumn>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
function PopupItem({ content, popKey }: { content: PopupContent; popKey: string }) {
|
function PopupItem({ content, popKey }: { content: PopupContent; popKey: string }) {
|
||||||
if ('txn' in content) {
|
if ('txn' in content) {
|
||||||
const {
|
const {
|
||||||
@ -81,20 +116,8 @@ function PopupItem({ content, popKey }: { content: PopupContent; popKey: string
|
|||||||
const {
|
const {
|
||||||
poolAdded: { token0, token1 }
|
poolAdded: { token0, token1 }
|
||||||
} = content
|
} = content
|
||||||
return (
|
|
||||||
<AutoColumn gap={'10px'}>
|
return <PoolPopup token0={token0} token1={token1} />
|
||||||
<Text fontSize={20} fontWeight={500}>
|
|
||||||
Pool Imported
|
|
||||||
</Text>
|
|
||||||
<Row>
|
|
||||||
<DoubleTokenLogo a0={token0?.address ?? ''} a1={token1?.address ?? ''} margin={true} />
|
|
||||||
<Text fontSize={16} fontWeight={500}>
|
|
||||||
UNI {token0?.symbol} / {token1?.symbol}
|
|
||||||
</Text>
|
|
||||||
</Row>
|
|
||||||
<Link>View on Uniswap Info.</Link>
|
|
||||||
</AutoColumn>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import Card, { GreyCard } from '../Card'
|
|||||||
import TokenLogo from '../TokenLogo'
|
import TokenLogo from '../TokenLogo'
|
||||||
import DoubleLogo from '../DoubleLogo'
|
import DoubleLogo from '../DoubleLogo'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { Link } from '../../theme/components'
|
import { ExternalLink } from '../../theme/components'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { ChevronDown, ChevronUp } from 'react-feather'
|
import { ChevronDown, ChevronUp } from 'react-feather'
|
||||||
import { ButtonSecondary } from '../Button'
|
import { ButtonSecondary } from '../Button'
|
||||||
@ -204,7 +204,9 @@ function PositionCard({ pair, history, border, minimal = false }: PositionCardPr
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<AutoRow justify="center" marginTop={'10px'}>
|
<AutoRow justify="center" marginTop={'10px'}>
|
||||||
<Link href={`https://uniswap.info/pair/${pair?.liquidityToken.address}`}>View pool information ↗</Link>
|
<ExternalLink href={`https://uniswap.info/pair/${pair?.liquidityToken.address}`}>
|
||||||
|
View pool information ↗
|
||||||
|
</ExternalLink>
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
<RowBetween marginTop="10px">
|
<RowBetween marginTop="10px">
|
||||||
<ButtonSecondary
|
<ButtonSecondary
|
||||||
|
@ -7,7 +7,7 @@ import { ThemeContext } from 'styled-components'
|
|||||||
import Circle from '../../assets/images/circle.svg'
|
import Circle from '../../assets/images/circle.svg'
|
||||||
import { ALL_TOKENS } from '../../constants/tokens'
|
import { ALL_TOKENS } from '../../constants/tokens'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { Link as StyledLink, TYPE } from '../../theme'
|
import { LinkStyledButton, TYPE } from '../../theme'
|
||||||
import { isAddress } from '../../utils'
|
import { isAddress } from '../../utils'
|
||||||
import { ButtonSecondary } from '../Button'
|
import { ButtonSecondary } from '../Button'
|
||||||
import Column, { AutoColumn } from '../Column'
|
import Column, { AutoColumn } from '../Column'
|
||||||
@ -87,7 +87,7 @@ export default function TokenList({
|
|||||||
onRemoveAddedToken(chainId, address)
|
onRemoveAddedToken(chainId, address)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<StyledLink style={{ marginLeft: '4px', fontWeight: 400 }}>(Remove)</StyledLink>
|
<LinkStyledButton style={{ marginLeft: '4px', fontWeight: 400 }}>(Remove)</LinkStyledButton>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</FadedSpan>
|
</FadedSpan>
|
||||||
|
@ -10,7 +10,7 @@ import { useActiveWeb3React } from '../../hooks'
|
|||||||
import { useAllTokens, useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens'
|
import { useAllTokens, useTokenByAddressAndAutomaticallyAdd } from '../../hooks/Tokens'
|
||||||
import { useAllDummyPairs, useRemoveUserAddedToken } from '../../state/user/hooks'
|
import { useAllDummyPairs, useRemoveUserAddedToken } from '../../state/user/hooks'
|
||||||
import { useAllTokenBalancesTreatingWETHasETH, useTokenBalances } from '../../state/wallet/hooks'
|
import { useAllTokenBalancesTreatingWETHasETH, useTokenBalances } from '../../state/wallet/hooks'
|
||||||
import { CloseIcon, Link as StyledLink } from '../../theme/components'
|
import { CloseIcon, LinkStyledButton, StyledInternalLink } from '../../theme/components'
|
||||||
import { isAddress } from '../../utils'
|
import { isAddress } from '../../utils'
|
||||||
import Column from '../Column'
|
import Column from '../Column'
|
||||||
import Modal from '../Modal'
|
import Modal from '../Modal'
|
||||||
@ -207,18 +207,12 @@ function SearchModal({
|
|||||||
<div>
|
<div>
|
||||||
{isTokenView ? (
|
{isTokenView ? (
|
||||||
<Text fontWeight={500} color={theme.text2} fontSize={14}>
|
<Text fontWeight={500} color={theme.text2} fontSize={14}>
|
||||||
<StyledLink onClick={openTooltip}>Having trouble finding a token?</StyledLink>
|
<LinkStyledButton onClick={openTooltip}>Having trouble finding a token?</LinkStyledButton>
|
||||||
</Text>
|
</Text>
|
||||||
) : (
|
) : (
|
||||||
<Text fontWeight={500}>
|
<Text fontWeight={500}>
|
||||||
{!isMobile && "Don't see a pool? "}
|
{!isMobile && "Don't see a pool? "}
|
||||||
<StyledLink
|
<StyledInternalLink to="/find">{!isMobile ? 'Import it.' : 'Import pool.'}</StyledInternalLink>
|
||||||
onClick={() => {
|
|
||||||
history.push('/find')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{!isMobile ? 'Import it.' : 'Import pool.'}
|
|
||||||
</StyledLink>
|
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -8,7 +8,7 @@ import { useActiveWeb3React } from '../../hooks'
|
|||||||
import { useAllTokens } from '../../hooks/Tokens'
|
import { useAllTokens } from '../../hooks/Tokens'
|
||||||
import { Field } from '../../state/swap/actions'
|
import { Field } from '../../state/swap/actions'
|
||||||
import { useTokenWarningDismissal } from '../../state/user/hooks'
|
import { useTokenWarningDismissal } from '../../state/user/hooks'
|
||||||
import { Link, TYPE } from '../../theme'
|
import { ExternalLink, TYPE } from '../../theme'
|
||||||
import { getEtherscanLink } from '../../utils'
|
import { getEtherscanLink } from '../../utils'
|
||||||
import PropsOfExcluding from '../../utils/props-of-excluding'
|
import PropsOfExcluding from '../../utils/props-of-excluding'
|
||||||
import QuestionHelper from '../QuestionHelper'
|
import QuestionHelper from '../QuestionHelper'
|
||||||
@ -111,9 +111,9 @@ export default function TokenWarningCard({ token, ...rest }: TokenWarningCardPro
|
|||||||
? `${token.name} (${token.symbol})`
|
? `${token.name} (${token.symbol})`
|
||||||
: token.name || token.symbol}
|
: token.name || token.symbol}
|
||||||
</div>
|
</div>
|
||||||
<Link style={{ fontWeight: 400 }} href={getEtherscanLink(chainId, token.address, 'address')}>
|
<ExternalLink style={{ fontWeight: 400 }} href={getEtherscanLink(chainId, token.address, 'address')}>
|
||||||
(View on Etherscan)
|
(View on Etherscan)
|
||||||
</Link>
|
</ExternalLink>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
<Row>
|
||||||
<TYPE.italic>Verify this is the correct token before making any transactions.</TYPE.italic>
|
<TYPE.italic>Verify this is the correct token before making any transactions.</TYPE.italic>
|
||||||
|
@ -8,7 +8,7 @@ import useInterval from '../../hooks/useInterval'
|
|||||||
import { useRemovePopup } from '../../state/application/hooks'
|
import { useRemovePopup } from '../../state/application/hooks'
|
||||||
import { TYPE } from '../../theme'
|
import { TYPE } from '../../theme'
|
||||||
|
|
||||||
import { Link } from '../../theme/components'
|
import { ExternalLink } from '../../theme/components'
|
||||||
import { getEtherscanLink } from '../../utils'
|
import { getEtherscanLink } from '../../utils'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
import { AutoRow } from '../Row'
|
import { AutoRow } from '../Row'
|
||||||
@ -62,7 +62,7 @@ export default function TxnPopup({
|
|||||||
<TYPE.body fontWeight={500}>
|
<TYPE.body fontWeight={500}>
|
||||||
{summary ? summary : 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}
|
{summary ? summary : 'Hash: ' + hash.slice(0, 8) + '...' + hash.slice(58, 65)}
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
<Link href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</Link>
|
<ExternalLink href={getEtherscanLink(chainId, hash, 'transaction')}>View on Etherscan</ExternalLink>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
<Fader count={count} />
|
<Fader count={count} />
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
|
|
||||||
const InfoCard = styled.button<{ active?: boolean }>`
|
const InfoCard = styled.button<{ active?: boolean }>`
|
||||||
background-color: ${({ theme, active }) => (active ? theme.bg3 : theme.bg2)};
|
background-color: ${({ theme, active }) => (active ? theme.bg3 : theme.bg2)};
|
||||||
@ -134,7 +134,7 @@ export default function Option({
|
|||||||
</OptionCardClickable>
|
</OptionCardClickable>
|
||||||
)
|
)
|
||||||
if (link) {
|
if (link) {
|
||||||
return <Link href={link}>{content}</Link>
|
return <ExternalLink href={link}>{content}</ExternalLink>
|
||||||
}
|
}
|
||||||
|
|
||||||
return content
|
return content
|
||||||
|
@ -12,7 +12,7 @@ import AccountDetails from '../AccountDetails'
|
|||||||
import PendingView from './PendingView'
|
import PendingView from './PendingView'
|
||||||
import Option from './Option'
|
import Option from './Option'
|
||||||
import { SUPPORTED_WALLETS } from '../../constants'
|
import { SUPPORTED_WALLETS } from '../../constants'
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
import MetamaskIcon from '../../assets/images/metamask.png'
|
import MetamaskIcon from '../../assets/images/metamask.png'
|
||||||
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
import { ReactComponent as Close } from '../../assets/images/x.svg'
|
||||||
import { injected, walletconnect, fortmatic, portis } from '../../connectors'
|
import { injected, walletconnect, fortmatic, portis } from '../../connectors'
|
||||||
@ -358,9 +358,9 @@ export default function WalletModal({
|
|||||||
{walletView !== WALLET_VIEWS.PENDING && (
|
{walletView !== WALLET_VIEWS.PENDING && (
|
||||||
<Blurb>
|
<Blurb>
|
||||||
<span>New to Ethereum? </span>{' '}
|
<span>New to Ethereum? </span>{' '}
|
||||||
<Link href="https://ethereum.org/use/#3-what-is-a-wallet-and-which-one-should-i-use">
|
<ExternalLink href="https://ethereum.org/use/#3-what-is-a-wallet-and-which-one-should-i-use">
|
||||||
Learn more about wallets
|
Learn more about wallets
|
||||||
</Link>
|
</ExternalLink>
|
||||||
</Blurb>
|
</Blurb>
|
||||||
)}
|
)}
|
||||||
</ContentWrapper>
|
</ContentWrapper>
|
||||||
|
@ -2,7 +2,7 @@ import { TokenAmount } from '@uniswap/sdk'
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { useActiveWeb3React } from '../../hooks'
|
import { useActiveWeb3React } from '../../hooks'
|
||||||
import { Link, TYPE } from '../../theme'
|
import { ExternalLink, TYPE } from '../../theme'
|
||||||
import { getEtherscanLink } from '../../utils'
|
import { getEtherscanLink } from '../../utils'
|
||||||
import Copy from '../AccountDetails/Copy'
|
import Copy from '../AccountDetails/Copy'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
@ -32,21 +32,21 @@ export function TransferModalHeader({
|
|||||||
<AutoColumn gap="lg">
|
<AutoColumn gap="lg">
|
||||||
<TYPE.blue fontSize={36}>{ENSName}</TYPE.blue>
|
<TYPE.blue fontSize={36}>{ENSName}</TYPE.blue>
|
||||||
<AutoRow gap="10px">
|
<AutoRow gap="10px">
|
||||||
<Link href={getEtherscanLink(chainId, ENSName, 'address')}>
|
<ExternalLink href={getEtherscanLink(chainId, ENSName, 'address')}>
|
||||||
<TYPE.blue fontSize={18}>
|
<TYPE.blue fontSize={18}>
|
||||||
{recipient?.slice(0, 8)}...{recipient?.slice(34, 42)}↗
|
{recipient?.slice(0, 8)}...{recipient?.slice(34, 42)}↗
|
||||||
</TYPE.blue>
|
</TYPE.blue>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
<Copy toCopy={recipient} />
|
<Copy toCopy={recipient} />
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
) : (
|
) : (
|
||||||
<AutoRow gap="10px">
|
<AutoRow gap="10px">
|
||||||
<Link href={getEtherscanLink(chainId, recipient, 'address')}>
|
<ExternalLink href={getEtherscanLink(chainId, recipient, 'address')}>
|
||||||
<TYPE.blue fontSize={36}>
|
<TYPE.blue fontSize={36}>
|
||||||
{recipient?.slice(0, 6)}...{recipient?.slice(36, 42)}↗
|
{recipient?.slice(0, 6)}...{recipient?.slice(36, 42)}↗
|
||||||
</TYPE.blue>
|
</TYPE.blue>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
<Copy toCopy={recipient} />
|
<Copy toCopy={recipient} />
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
)}
|
)}
|
||||||
|
@ -2,7 +2,7 @@ import React, { useContext } from 'react'
|
|||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { ThemeContext } from 'styled-components'
|
import { ThemeContext } from 'styled-components'
|
||||||
|
|
||||||
import { Link } from '../../theme'
|
import { ExternalLink } from '../../theme'
|
||||||
import { YellowCard } from '../Card'
|
import { YellowCard } from '../Card'
|
||||||
import { AutoColumn } from '../Column'
|
import { AutoColumn } from '../Column'
|
||||||
|
|
||||||
@ -12,10 +12,10 @@ export default function V1TradeLink({ v1TradeLinkIfBetter }: { v1TradeLinkIfBett
|
|||||||
<YellowCard style={{ marginTop: '12px', padding: '8px 4px' }}>
|
<YellowCard style={{ marginTop: '12px', padding: '8px 4px' }}>
|
||||||
<AutoColumn gap="sm" justify="center" style={{ alignItems: 'center', textAlign: 'center' }}>
|
<AutoColumn gap="sm" justify="center" style={{ alignItems: 'center', textAlign: 'center' }}>
|
||||||
<Text lineHeight="145.23%;" fontSize={14} fontWeight={400} color={theme.text1}>
|
<Text lineHeight="145.23%;" fontSize={14} fontWeight={400} color={theme.text1}>
|
||||||
There is a better price for this trade on
|
There is a better price for this trade on{' '}
|
||||||
<Link href={v1TradeLinkIfBetter}>
|
<ExternalLink href={v1TradeLinkIfBetter}>
|
||||||
<b> Uniswap V1 ↗</b>
|
<b>Uniswap V1 ↗</b>
|
||||||
</Link>
|
</ExternalLink>
|
||||||
</Text>
|
</Text>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</YellowCard>
|
</YellowCard>
|
||||||
|
@ -36,7 +36,7 @@ import { useApproveCallback, ApprovalState } from '../../hooks/useApproveCallbac
|
|||||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||||
import AdvancedSwapDetailsDropdown from '../../components/swap/AdvancedSwapDetailsDropdown'
|
import AdvancedSwapDetailsDropdown from '../../components/swap/AdvancedSwapDetailsDropdown'
|
||||||
|
|
||||||
export default function AddLiquidity({ match: { params } }: RouteComponentProps<{ tokens: string }>) {
|
export default function AddLiquidity({ match: { params }, history }: RouteComponentProps<{ tokens: string }>) {
|
||||||
useDefaultsFromURLMatchParams(params)
|
useDefaultsFromURLMatchParams(params)
|
||||||
|
|
||||||
const { account, chainId, library } = useActiveWeb3React()
|
const { account, chainId, library } = useActiveWeb3React()
|
||||||
@ -311,6 +311,10 @@ export default function AddLiquidity({ match: { params } }: RouteComponentProps<
|
|||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
isOpen={showConfirm}
|
isOpen={showConfirm}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
|
if (attemptingTxn) {
|
||||||
|
history.push('/pool')
|
||||||
|
return
|
||||||
|
}
|
||||||
setPendingConfirmation(true)
|
setPendingConfirmation(true)
|
||||||
setAttemptingTxn(false)
|
setAttemptingTxn(false)
|
||||||
setShowConfirm(false)
|
setShowConfirm(false)
|
||||||
|
@ -8,7 +8,7 @@ import TokenLogo from '../../components/TokenLogo'
|
|||||||
import SearchModal from '../../components/SearchModal'
|
import SearchModal from '../../components/SearchModal'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { Plus } from 'react-feather'
|
import { Plus } from 'react-feather'
|
||||||
import { TYPE, Link } from '../../theme'
|
import { TYPE, StyledInternalLink } from '../../theme'
|
||||||
import { AutoColumn, ColumnCenter } from '../../components/Column'
|
import { AutoColumn, ColumnCenter } from '../../components/Column'
|
||||||
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../../components/Button'
|
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../../components/Button'
|
||||||
|
|
||||||
@ -27,7 +27,7 @@ enum STEP {
|
|||||||
SHOW_CREATE_PAGE = 'SHOW_CREATE_PAGE' // show create page
|
SHOW_CREATE_PAGE = 'SHOW_CREATE_PAGE' // show create page
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function CreatePool({ history, location }: RouteComponentProps) {
|
export default function CreatePool({ location }: RouteComponentProps) {
|
||||||
const { chainId } = useActiveWeb3React()
|
const { chainId } = useActiveWeb3React()
|
||||||
const [showSearch, setShowSearch] = useState<boolean>(false)
|
const [showSearch, setShowSearch] = useState<boolean>(false)
|
||||||
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
|
const [activeField, setActiveField] = useState<number>(Fields.TOKEN0)
|
||||||
@ -116,8 +116,8 @@ export default function CreatePool({ history, location }: RouteComponentProps) {
|
|||||||
{pair ? ( // pair already exists - prompt to add liquidity to existing pool
|
{pair ? ( // pair already exists - prompt to add liquidity to existing pool
|
||||||
<AutoRow padding="10px" justify="center">
|
<AutoRow padding="10px" justify="center">
|
||||||
<TYPE.body textAlign="center">
|
<TYPE.body textAlign="center">
|
||||||
Pool already exists!
|
Pool already exists!{' '}
|
||||||
<Link onClick={() => history.push('/add/' + token0Address + '-' + token1Address)}> Join the pool.</Link>
|
<StyledInternalLink to={`/add/${token0Address}-${token1Address}`}>Join the pool.</StyledInternalLink>
|
||||||
</TYPE.body>
|
</TYPE.body>
|
||||||
</AutoRow>
|
</AutoRow>
|
||||||
) : (
|
) : (
|
||||||
|
@ -8,7 +8,7 @@ import SearchModal from '../../components/SearchModal'
|
|||||||
import PositionCard from '../../components/PositionCard'
|
import PositionCard from '../../components/PositionCard'
|
||||||
import { useUserProbablyHasV1Liquidity } from '../../data/V1'
|
import { useUserProbablyHasV1Liquidity } from '../../data/V1'
|
||||||
import { useTokenBalances } from '../../state/wallet/hooks'
|
import { useTokenBalances } from '../../state/wallet/hooks'
|
||||||
import { Link, TYPE } from '../../theme'
|
import { LinkStyledButton, StyledInternalLink, TYPE } from '../../theme'
|
||||||
import { Text } from 'rebass'
|
import { Text } from 'rebass'
|
||||||
import { LightCard } from '../../components/Card'
|
import { LightCard } from '../../components/Card'
|
||||||
import { RowBetween } from '../../components/Row'
|
import { RowBetween } from '../../components/Row'
|
||||||
@ -98,19 +98,12 @@ export default function Pool({ history }: RouteComponentProps) {
|
|||||||
{!hasV1Liquidity ? (
|
{!hasV1Liquidity ? (
|
||||||
<>
|
<>
|
||||||
{filteredExchangeList?.length !== 0 ? `Don't see a pool you joined? ` : 'Already joined a pool? '}{' '}
|
{filteredExchangeList?.length !== 0 ? `Don't see a pool you joined? ` : 'Already joined a pool? '}{' '}
|
||||||
<Link
|
<StyledInternalLink id="import-pool-link" to="/find">
|
||||||
id="import-pool-link"
|
|
||||||
onClick={() => {
|
|
||||||
history.push('/find')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Import it.
|
Import it.
|
||||||
</Link>
|
</StyledInternalLink>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<Link id="migrate-v1-liquidity-link" href="https://migrate.uniswap.exchange">
|
<LinkStyledButton id="migrate-v1-liquidity-link">Migrate your V1 liquidity.</LinkStyledButton>
|
||||||
Migrate your V1 liquidity.
|
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
</Text>
|
</Text>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
|
@ -15,7 +15,7 @@ import { useActiveWeb3React } from '../../hooks'
|
|||||||
import { useToken } from '../../hooks/Tokens'
|
import { useToken } from '../../hooks/Tokens'
|
||||||
import { usePairAdder } from '../../state/user/hooks'
|
import { usePairAdder } from '../../state/user/hooks'
|
||||||
import { useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks'
|
import { useTokenBalanceTreatingWETHasETH } from '../../state/wallet/hooks'
|
||||||
import { Link } from '../../theme'
|
import { StyledInternalLink } from '../../theme'
|
||||||
import AppBody from '../AppBody'
|
import AppBody from '../AppBody'
|
||||||
|
|
||||||
enum Fields {
|
enum Fields {
|
||||||
@ -119,13 +119,9 @@ export default function PoolFinder({ history }: RouteComponentProps) {
|
|||||||
<LightCard padding="45px 10px">
|
<LightCard padding="45px 10px">
|
||||||
<AutoColumn gap="sm" justify="center">
|
<AutoColumn gap="sm" justify="center">
|
||||||
<Text textAlign="center">Pool found, you don’t have liquidity on this pair yet.</Text>
|
<Text textAlign="center">Pool found, you don’t have liquidity on this pair yet.</Text>
|
||||||
<Link
|
<StyledInternalLink to={`/add/${token0Address}-${token1Address}`}>
|
||||||
onClick={() => {
|
|
||||||
history.push('/add/' + token0Address + '-' + token1Address)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text textAlign="center">Add liquidity to this pair instead.</Text>
|
<Text textAlign="center">Add liquidity to this pair instead.</Text>
|
||||||
</Link>
|
</StyledInternalLink>
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
)
|
)
|
||||||
@ -133,13 +129,7 @@ export default function PoolFinder({ history }: RouteComponentProps) {
|
|||||||
<LightCard padding="45px">
|
<LightCard padding="45px">
|
||||||
<AutoColumn gap="sm" justify="center">
|
<AutoColumn gap="sm" justify="center">
|
||||||
<Text color="">No pool found.</Text>
|
<Text color="">No pool found.</Text>
|
||||||
<Link
|
<StyledInternalLink to={`/add/${token0Address}-${token1Address}`}>Create pool?</StyledInternalLink>
|
||||||
onClick={() => {
|
|
||||||
history.push('/add/' + token0Address + '-' + token1Address)
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Create pool?
|
|
||||||
</Link>
|
|
||||||
</AutoColumn>
|
</AutoColumn>
|
||||||
</LightCard>
|
</LightCard>
|
||||||
) : (
|
) : (
|
||||||
|
@ -35,7 +35,7 @@ import AdvancedSwapDetailsDropdown from '../../components/swap/AdvancedSwapDetai
|
|||||||
import { Field } from '../../state/burn/actions'
|
import { Field } from '../../state/burn/actions'
|
||||||
import { useWalletModalToggle } from '../../state/application/hooks'
|
import { useWalletModalToggle } from '../../state/application/hooks'
|
||||||
|
|
||||||
export default function RemoveLiquidity({ match: { params } }: RouteComponentProps<{ tokens: string }>) {
|
export default function RemoveLiquidity({ match: { params }, history }: RouteComponentProps<{ tokens: string }>) {
|
||||||
useDefaultsFromURLMatchParams(params)
|
useDefaultsFromURLMatchParams(params)
|
||||||
|
|
||||||
const { account, chainId, library } = useActiveWeb3React()
|
const { account, chainId, library } = useActiveWeb3React()
|
||||||
@ -398,6 +398,10 @@ export default function RemoveLiquidity({ match: { params } }: RouteComponentPro
|
|||||||
<ConfirmationModal
|
<ConfirmationModal
|
||||||
isOpen={showConfirm}
|
isOpen={showConfirm}
|
||||||
onDismiss={() => {
|
onDismiss={() => {
|
||||||
|
if (attemptingTxn) {
|
||||||
|
history.push('/pool')
|
||||||
|
return
|
||||||
|
}
|
||||||
resetModalState()
|
resetModalState()
|
||||||
setShowConfirm(false)
|
setShowConfirm(false)
|
||||||
setShowAdvanced(false)
|
setShowAdvanced(false)
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { HTMLProps, useCallback } from 'react'
|
import React, { HTMLProps, useCallback } from 'react'
|
||||||
import ReactGA from 'react-ga'
|
import ReactGA from 'react-ga'
|
||||||
|
import { Link } from 'react-router-dom'
|
||||||
import styled, { keyframes } from 'styled-components'
|
import styled, { keyframes } from 'styled-components'
|
||||||
import { darken } from 'polished'
|
import { darken } from 'polished'
|
||||||
import { X } from 'react-feather'
|
import { X } from 'react-feather'
|
||||||
@ -38,6 +39,51 @@ export const CloseIcon = styled(X)<{ onClick: () => void }>`
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// A button that triggers some onClick result, but looks like a link.
|
||||||
|
export const LinkStyledButton = styled.button`
|
||||||
|
border: none;
|
||||||
|
text-decoration: none;
|
||||||
|
background: none;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
color: ${({ theme }) => theme.primary1};
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus {
|
||||||
|
outline: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
:active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
// An internal link from the react-router-dom library that is correctly styled
|
||||||
|
export const StyledInternalLink = styled(Link)`
|
||||||
|
text-decoration: none;
|
||||||
|
cursor: pointer;
|
||||||
|
color: ${({ theme }) => theme.primary1};
|
||||||
|
font-weight: 500;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
:focus {
|
||||||
|
outline: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
:active {
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const StyledLink = styled.a`
|
const StyledLink = styled.a`
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -58,20 +104,19 @@ const StyledLink = styled.a`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
export function Link({
|
/**
|
||||||
onClick,
|
* Outbound link that handles firing google analytics events
|
||||||
|
*/
|
||||||
|
export function ExternalLink({
|
||||||
target = '_blank',
|
target = '_blank',
|
||||||
href,
|
href,
|
||||||
rel = 'noopener noreferrer',
|
rel = 'noopener noreferrer',
|
||||||
...rest
|
...rest
|
||||||
}: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref'>) {
|
}: Omit<HTMLProps<HTMLAnchorElement>, 'as' | 'ref' | 'onClick'> & { href: string }) {
|
||||||
const handleClick = useCallback(
|
const handleClick = useCallback(
|
||||||
(event: React.MouseEvent<HTMLAnchorElement>) => {
|
(event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||||
onClick && onClick(event) // first call back into the original onClick
|
// don't prevent default, don't redirect if it's a new tab
|
||||||
if (!href) return
|
if (target === '_blank' || event.ctrlKey || event.metaKey) {
|
||||||
|
|
||||||
// don't prevent default, don't redirect
|
|
||||||
if (target === '_blank') {
|
|
||||||
ReactGA.outboundLink({ label: href }, () => {
|
ReactGA.outboundLink({ label: href }, () => {
|
||||||
console.debug('Fired outbound link event', href)
|
console.debug('Fired outbound link event', href)
|
||||||
})
|
})
|
||||||
@ -83,7 +128,7 @@ export function Link({
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[href, onClick, target]
|
[href, target]
|
||||||
)
|
)
|
||||||
return <StyledLink target={target} rel={rel} href={href} onClick={handleClick} {...rest} />
|
return <StyledLink target={target} rel={rel} href={href} onClick={handleClick} {...rest} />
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user