chore(cleanup): separate the components for 3 kinds of links we use

This commit is contained in:
Moody Salem 2020-05-30 23:33:16 -04:00
parent 98d25dd2af
commit e2d0514344
No known key found for this signature in database
GPG Key ID: 8CB5CD10385138DB
23 changed files with 176 additions and 129 deletions

@ -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&nbsp; Uniswap V2 is live! Read the&nbsp;
<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>
&nbsp;or&nbsp; &nbsp;or&nbsp;
<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? &nbsp;</span>{' '} <span>New to Ethereum? &nbsp;</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 dont have liquidity on this pair yet.</Text> <Text textAlign="center">Pool found, you dont 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} />
} }