Commit a1b37766 authored by Jordan Frankfurt's avatar Jordan Frankfurt Committed by GitHub

feat: vertical LP (#7000)

* Re-organize add liquidity page

* fix title alignment

* Update styles

* Update logic for disable/enable input on creation

* lint and clean up a couple small things

* lint and clean up a couple small things

* Tweak UI

* clean up code

* add back range selector

* remove inline styles

---------
Co-authored-by: default avatarCallil Capuozzo <callil@uniswap.org>
parent dc2225a2
...@@ -4,12 +4,10 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core' ...@@ -4,12 +4,10 @@ import { Currency, CurrencyAmount } from '@uniswap/sdk-core'
import { Pair } from '@uniswap/v2-sdk' import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { TraceEvent } from 'analytics' import { TraceEvent } from 'analytics'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled' import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
import { darken } from 'polished' import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react' import { ReactNode, useCallback, useState } from 'react'
import { Lock } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro' import styled, { useTheme } from 'styled-components/macro'
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles' import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount' import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
...@@ -36,18 +34,6 @@ const InputPanel = styled.div<{ hideInput?: boolean }>` ...@@ -36,18 +34,6 @@ const InputPanel = styled.div<{ hideInput?: boolean }>`
will-change: height; will-change: height;
` `
const FixedContainer = styled.div`
width: 100%;
height: 100%;
position: absolute;
border-radius: 16px;
background-color: ${({ theme }) => theme.backgroundInteractive};
display: flex;
align-items: center;
justify-content: center;
z-index: 2;
`
const Container = styled.div<{ hideInput: boolean; disabled: boolean }>` const Container = styled.div<{ hideInput: boolean; disabled: boolean }>`
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')}; border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
border: 1px solid ${({ theme }) => theme.backgroundSurface}; border: 1px solid ${({ theme }) => theme.backgroundSurface};
...@@ -226,110 +212,99 @@ export default function CurrencyInputPanel({ ...@@ -226,110 +212,99 @@ export default function CurrencyInputPanel({
return ( return (
<InputPanel id={id} hideInput={hideInput} {...rest}> <InputPanel id={id} hideInput={hideInput} {...rest}>
{locked && ( {!locked && (
<FixedContainer> <>
<AutoColumn gap="sm" justify="center"> <Container hideInput={hideInput} disabled={!chainAllowed}>
<Lock /> <InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}>
<ThemedText.DeprecatedLabel fontSize="12px" textAlign="center" padding="0 12px"> {!hideInput && (
<Trans>The market price is outside your specified price range. Single-asset deposit only.</Trans> <StyledNumericalInput
</ThemedText.DeprecatedLabel> className="token-amount-input"
</AutoColumn> value={value}
</FixedContainer> onUserInput={onUserInput}
)} disabled={!chainAllowed}
<Container hideInput={hideInput} disabled={!chainAllowed}> $loading={loading}
<InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}> />
{!hideInput && (
<StyledNumericalInput
className="token-amount-input"
value={value}
onUserInput={onUserInput}
disabled={!chainAllowed}
$loading={loading}
/>
)}
<CurrencySelect
disabled={!chainAllowed}
visible={currency !== undefined}
selected={!!currency}
hideInput={hideInput}
className="open-currency-select-button"
onClick={() => {
if (onCurrencySelect) {
setModalOpen(true)
}
}}
pointerEvents={!onCurrencySelect ? 'none' : undefined}
>
<Aligner>
<RowFixed>
{pair ? (
<span style={{ marginRight: '0.5rem' }}>
<DoubleCurrencyLogo currency0={pair.token0} currency1={pair.token1} size={24} margin={true} />
</span>
) : currency ? (
<CurrencyLogo style={{ marginRight: '0.5rem' }} currency={currency} size="24px" />
) : null}
{pair ? (
<StyledTokenName className="pair-name-container">
{pair?.token0.symbol}:{pair?.token1.symbol}
</StyledTokenName>
) : (
<StyledTokenName className="token-symbol-container" active={Boolean(currency && currency.symbol)}>
{(currency && currency.symbol && currency.symbol.length > 20
? currency.symbol.slice(0, 4) +
'...' +
currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length)
: currency?.symbol) || <Trans>Select a token</Trans>}
</StyledTokenName>
)}
</RowFixed>
{onCurrencySelect && <StyledDropDown selected={!!currency} />}
</Aligner>
</CurrencySelect>
</InputRow>
{!hideInput && !hideBalance && currency && (
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
{fiatValue && <FiatValue fiatValue={fiatValue} />}
</LoadingOpacityContainer>
{account ? (
<RowFixed style={{ height: '17px' }}>
<ThemedText.DeprecatedBody
onClick={onMax}
color={theme.textTertiary}
fontWeight={500}
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}
>
{!hideBalance && currency && selectedCurrencyBalance ? (
renderBalance ? (
renderBalance(selectedCurrencyBalance)
) : (
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)}</Trans>
)
) : null}
</ThemedText.DeprecatedBody>
{showMaxButton && selectedCurrencyBalance ? (
<TraceEvent
events={[BrowserEvent.onClick]}
name={SwapEventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
element={InterfaceElementName.MAX_TOKEN_AMOUNT_BUTTON}
>
<StyledBalanceMax onClick={onMax}>
<Trans>MAX</Trans>
</StyledBalanceMax>
</TraceEvent>
) : null}
</RowFixed>
) : (
<span />
)} )}
</RowBetween>
</FiatRow> <CurrencySelect
)} disabled={!chainAllowed}
</Container> visible={currency !== undefined}
selected={!!currency}
hideInput={hideInput}
className="open-currency-select-button"
onClick={() => {
if (onCurrencySelect) {
setModalOpen(true)
}
}}
pointerEvents={!onCurrencySelect ? 'none' : undefined}
>
<Aligner>
<RowFixed>
{pair ? (
<span style={{ marginRight: '0.5rem' }}>
<DoubleCurrencyLogo currency0={pair.token0} currency1={pair.token1} size={24} margin={true} />
</span>
) : (
currency && <CurrencyLogo style={{ marginRight: '0.5rem' }} currency={currency} size="24px" />
)}
{pair ? (
<StyledTokenName className="pair-name-container">
{pair?.token0.symbol}:{pair?.token1.symbol}
</StyledTokenName>
) : (
<StyledTokenName className="token-symbol-container" active={Boolean(currency && currency.symbol)}>
{(currency && currency.symbol && currency.symbol.length > 20
? currency.symbol.slice(0, 4) +
'...' +
currency.symbol.slice(currency.symbol.length - 5, currency.symbol.length)
: currency?.symbol) || <Trans>Select a token</Trans>}
</StyledTokenName>
)}
</RowFixed>
{onCurrencySelect && <StyledDropDown selected={!!currency} />}
</Aligner>
</CurrencySelect>
</InputRow>
{Boolean(!hideInput && !hideBalance && currency) && (
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
{fiatValue && <FiatValue fiatValue={fiatValue} />}
</LoadingOpacityContainer>
{account && (
<RowFixed style={{ height: '17px' }}>
<ThemedText.DeprecatedBody
onClick={onMax}
color={theme.textTertiary}
fontWeight={500}
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}
>
{Boolean(!hideBalance && currency && selectedCurrencyBalance) &&
(renderBalance?.(selectedCurrencyBalance as CurrencyAmount<Currency>) || (
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)}</Trans>
))}
</ThemedText.DeprecatedBody>
{Boolean(showMaxButton && selectedCurrencyBalance) && (
<TraceEvent
events={[BrowserEvent.onClick]}
name={SwapEventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
element={InterfaceElementName.MAX_TOKEN_AMOUNT_BUTTON}
>
<StyledBalanceMax onClick={onMax}>
<Trans>MAX</Trans>
</StyledBalanceMax>
</TraceEvent>
)}
</RowFixed>
)}
</RowBetween>
</FiatRow>
)}
</Container>
</>
)}
{onCurrencySelect && ( {onCurrencySelect && (
<CurrencySearchModal <CurrencySearchModal
isOpen={modalOpen} isOpen={modalOpen}
......
...@@ -25,9 +25,7 @@ const pulse = (color: string) => keyframes` ...@@ -25,9 +25,7 @@ const pulse = (color: string) => keyframes`
` `
const InputRow = styled.div` const InputRow = styled.div`
display: grid; display: flex;
grid-template-columns: 30px 1fr 30px;
` `
const SmallButton = styled(ButtonGray)` const SmallButton = styled(ButtonGray)`
...@@ -43,18 +41,17 @@ const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boo ...@@ -43,18 +41,17 @@ const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boo
const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>` const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
background-color: transparent; background-color: transparent;
text-align: center;
width: 100%;
font-weight: 500; font-weight: 500;
padding: 0 10px; text-align: left;
width: 100%;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall`
font-size: 16px; font-size: 16px;
`}; `};
`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToExtraSmall` const InputColumn = styled(AutoColumn)`
font-size: 12px; width: 100%;
`};
` `
const InputTitle = styled(ThemedText.DeprecatedSmall)` const InputTitle = styled(ThemedText.DeprecatedSmall)`
...@@ -142,20 +139,11 @@ const StepCounter = ({ ...@@ -142,20 +139,11 @@ const StepCounter = ({
return ( return (
<FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}> <FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}>
<AutoColumn gap="6px"> <InputRow>
<InputTitle fontSize={12} textAlign="center"> <InputColumn justify="flex-start">
{title} <InputTitle fontSize={12} textAlign="center">
</InputTitle> {title}
</InputTitle>
<InputRow>
{!locked && (
<SmallButton data-testid="decrement-price-range" onClick={handleDecrement} disabled={decrementDisabled}>
<ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Minus size={18} />
</ButtonLabel>
</SmallButton>
)}
<StyledInput <StyledInput
className="rate-input-0" className="rate-input-0"
value={localValue} value={localValue}
...@@ -165,7 +153,14 @@ const StepCounter = ({ ...@@ -165,7 +153,14 @@ const StepCounter = ({
setLocalValue(val) setLocalValue(val)
}} }}
/> />
<InputTitle fontSize={12} textAlign="left">
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
</InputColumn>
<AutoColumn gap="8px">
{!locked && ( {!locked && (
<SmallButton data-testid="increment-price-range" onClick={handleIncrement} disabled={incrementDisabled}> <SmallButton data-testid="increment-price-range" onClick={handleIncrement} disabled={incrementDisabled}>
<ButtonLabel disabled={incrementDisabled} fontSize="12px"> <ButtonLabel disabled={incrementDisabled} fontSize="12px">
...@@ -173,14 +168,15 @@ const StepCounter = ({ ...@@ -173,14 +168,15 @@ const StepCounter = ({
</ButtonLabel> </ButtonLabel>
</SmallButton> </SmallButton>
)} )}
</InputRow> {!locked && (
<SmallButton data-testid="decrement-price-range" onClick={handleDecrement} disabled={decrementDisabled}>
<InputTitle fontSize={12} textAlign="center"> <ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Trans> <Minus size={18} />
{tokenB} per {tokenA} </ButtonLabel>
</Trans> </SmallButton>
</InputTitle> )}
</AutoColumn> </AutoColumn>
</InputRow>
</FocusedOutlineCard> </FocusedOutlineCard>
) )
} }
......
...@@ -12,7 +12,7 @@ const Wrapper = styled.div<{ count: number }>` ...@@ -12,7 +12,7 @@ const Wrapper = styled.div<{ count: number }>`
grid-gap: 6px; grid-gap: 6px;
position: absolute; position: absolute;
top: -75px; top: -32px;
right: 0; right: 0;
` `
......
...@@ -6,7 +6,7 @@ import Loader from 'components/Icons/LoadingSpinner' ...@@ -6,7 +6,7 @@ import Loader from 'components/Icons/LoadingSpinner'
import { format } from 'd3' import { format } from 'd3'
import { useColor } from 'hooks/useColor' import { useColor } from 'hooks/useColor'
import { saturate } from 'polished' import { saturate } from 'polished'
import React, { ReactNode, useCallback, useMemo } from 'react' import { ReactNode, useCallback, useMemo } from 'react'
import { BarChart2, CloudOff, Inbox } from 'react-feather' import { BarChart2, CloudOff, Inbox } from 'react-feather'
import { batch } from 'react-redux' import { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
...@@ -46,7 +46,8 @@ const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = { ...@@ -46,7 +46,8 @@ const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = {
const ChartWrapper = styled.div` const ChartWrapper = styled.div`
position: relative; position: relative;
width: 100%;
max-height: 200px;
justify-content: center; justify-content: center;
align-content: center; align-content: center;
` `
...@@ -180,7 +181,7 @@ export default function LiquidityChartRangeInput({ ...@@ -180,7 +181,7 @@ export default function LiquidityChartRangeInput({
<ChartWrapper> <ChartWrapper>
<Chart <Chart
data={{ series: formattedData, current: price }} data={{ series: formattedData, current: price }}
dimensions={{ width: 400, height: 200 }} dimensions={{ width: 560, height: 200 }}
margins={{ top: 10, right: 2, bottom: 20, left: 0 }} margins={{ top: 10, right: 2, bottom: 20, left: 0 }}
styles={{ styles={{
area: { area: {
......
...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core' ...@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import { ArrowLeft } from 'react-feather' import { ArrowLeft } from 'react-feather'
import { Link as HistoryLink, useLocation } from 'react-router-dom' import { Link, useLocation } from 'react-router-dom'
import { Box } from 'rebass' import { Box } from 'rebass'
import { useAppDispatch } from 'state/hooks' import { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions' import { resetMintState } from 'state/mint/actions'
...@@ -12,7 +12,7 @@ import styled, { useTheme } from 'styled-components/macro' ...@@ -12,7 +12,7 @@ import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
import { flexRowNoWrap } from 'theme/styles' import { flexRowNoWrap } from 'theme/styles'
import Row, { RowBetween } from '../Row' import { RowBetween } from '../Row'
import SettingsTab from '../Settings' import SettingsTab from '../Settings'
const Tabs = styled.div` const Tabs = styled.div`
...@@ -22,7 +22,7 @@ const Tabs = styled.div` ...@@ -22,7 +22,7 @@ const Tabs = styled.div`
justify-content: space-evenly; justify-content: space-evenly;
` `
const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>` const StyledLink = styled(Link)<{ flex?: string }>`
flex: ${({ flex }) => flex ?? 'none'}; flex: ${({ flex }) => flex ?? 'none'};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
...@@ -31,9 +31,10 @@ const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>` ...@@ -31,9 +31,10 @@ const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>`
`}; `};
` `
const ActiveText = styled.div` const FindPoolTabsText = styled(ThemedText.SubHeaderLarge)`
font-weight: 500; position: absolute;
font-size: 20px; left: 50%;
transform: translateX(-50%);
` `
const StyledArrowLeft = styled(ArrowLeft)` const StyledArrowLeft = styled(ArrowLeft)`
...@@ -44,17 +45,22 @@ export function FindPoolTabs({ origin }: { origin: string }) { ...@@ -44,17 +45,22 @@ export function FindPoolTabs({ origin }: { origin: string }) {
return ( return (
<Tabs> <Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem', position: 'relative' }}> <RowBetween style={{ padding: '1rem 1rem 0 1rem', position: 'relative' }}>
<HistoryLink to={origin}> <Link to={origin}>
<StyledArrowLeft /> <StyledArrowLeft />
</HistoryLink> </Link>
<ActiveText style={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)' }}> <FindPoolTabsText>
<Trans>Import V2 Pool</Trans> <Trans>Import V2 Pool</Trans>
</ActiveText> </FindPoolTabsText>
</RowBetween> </RowBetween>
</Tabs> </Tabs>
) )
} }
const AddRemoveTitleText = styled(ThemedText.SubHeaderLarge)`
flex: 1;
margin: auto;
`
export function AddRemoveTabs({ export function AddRemoveTabs({
adding, adding,
creating, creating,
...@@ -83,7 +89,7 @@ export function AddRemoveTabs({ ...@@ -83,7 +89,7 @@ export function AddRemoveTabs({
return ( return (
<Tabs> <Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}> <RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
<StyledHistoryLink <StyledLink
to={poolLink} to={poolLink}
onClick={() => { onClick={() => {
if (adding) { if (adding) {
...@@ -95,12 +101,8 @@ export function AddRemoveTabs({ ...@@ -95,12 +101,8 @@ export function AddRemoveTabs({
flex={children ? '1' : undefined} flex={children ? '1' : undefined}
> >
<StyledArrowLeft stroke={theme.textSecondary} /> <StyledArrowLeft stroke={theme.textSecondary} />
</StyledHistoryLink> </StyledLink>
<ThemedText.DeprecatedMediumHeader <AddRemoveTitleText textAlign={children ? 'start' : 'center'}>
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
>
{creating ? ( {creating ? (
<Trans>Create a pair</Trans> <Trans>Create a pair</Trans>
) : adding ? ( ) : adding ? (
...@@ -108,23 +110,10 @@ export function AddRemoveTabs({ ...@@ -108,23 +110,10 @@ export function AddRemoveTabs({
) : ( ) : (
<Trans>Remove Liquidity</Trans> <Trans>Remove Liquidity</Trans>
)} )}
</ThemedText.DeprecatedMediumHeader> </AddRemoveTitleText>
<Box style={{ marginRight: '.5rem' }}>{children}</Box> {children && <Box style={{ marginRight: '.5rem' }}>{children}</Box>}
<SettingsTab autoSlippage={autoSlippage} chainId={chainId} /> <SettingsTab autoSlippage={autoSlippage} chainId={chainId} />
</RowBetween> </RowBetween>
</Tabs> </Tabs>
) )
} }
export function CreateProposalTabs() {
return (
<Tabs>
<Row style={{ padding: '1rem 1rem 0 1rem' }}>
<HistoryLink to="/vote">
<StyledArrowLeft />
</HistoryLink>
<ActiveText style={{ marginLeft: 'auto', marginRight: 'auto' }}>Create Proposal</ActiveText>
</Row>
</Tabs>
)
}
...@@ -5,7 +5,7 @@ import styled from 'styled-components/macro' ...@@ -5,7 +5,7 @@ import styled from 'styled-components/macro'
import { ThemedText } from 'theme' import { ThemedText } from 'theme'
const Button = styled(ButtonOutlined).attrs(() => ({ const Button = styled(ButtonOutlined).attrs(() => ({
padding: '8px', padding: '6px',
$borderRadius: '8px', $borderRadius: '8px',
}))` }))`
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
......
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import { Currency, Price, Token } from '@uniswap/sdk-core' import { Currency, Price, Token } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column'
import StepCounter from 'components/InputStepCounter/InputStepCounter' import StepCounter from 'components/InputStepCounter/InputStepCounter'
import { RowBetween } from 'components/Row' import { AutoRow } from 'components/Row'
import { Bound } from 'state/mint/v3/actions' import { Bound } from 'state/mint/v3/actions'
// currencyA is the base token // currencyA is the base token
...@@ -41,37 +40,33 @@ export default function RangeSelector({ ...@@ -41,37 +40,33 @@ export default function RangeSelector({
const rightPrice = isSorted ? priceUpper : priceLower?.invert() const rightPrice = isSorted ? priceUpper : priceLower?.invert()
return ( return (
<AutoColumn gap="md"> <AutoRow gap="md">
<RowBetween> <StepCounter
<StepCounter value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(8) ?? ''}
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(5) ?? ''} onUserInput={onLeftRangeInput}
onUserInput={onLeftRangeInput} decrement={isSorted ? getDecrementLower : getIncrementUpper}
width="48%" increment={isSorted ? getIncrementLower : getDecrementUpper}
decrement={isSorted ? getDecrementLower : getIncrementUpper} decrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
increment={isSorted ? getIncrementLower : getDecrementUpper} incrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
decrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]} feeAmount={feeAmount}
incrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]} label={leftPrice ? `${currencyB?.symbol}` : '-'}
feeAmount={feeAmount} title={<Trans>Low price</Trans>}
label={leftPrice ? `${currencyB?.symbol}` : '-'} tokenA={currencyA?.symbol}
title={<Trans>Min Price</Trans>} tokenB={currencyB?.symbol}
tokenA={currencyA?.symbol} />
tokenB={currencyB?.symbol} <StepCounter
/> value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(8) ?? ''}
<StepCounter onUserInput={onRightRangeInput}
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(5) ?? ''} decrement={isSorted ? getDecrementUpper : getIncrementLower}
onUserInput={onRightRangeInput} increment={isSorted ? getIncrementUpper : getDecrementLower}
width="48%" incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
decrement={isSorted ? getDecrementUpper : getIncrementLower} decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
increment={isSorted ? getIncrementUpper : getDecrementLower} feeAmount={feeAmount}
incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]} label={rightPrice ? `${currencyB?.symbol}` : '-'}
decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]} tokenA={currencyA?.symbol}
feeAmount={feeAmount} tokenB={currencyB?.symbol}
label={rightPrice ? `${currencyB?.symbol}` : '-'} title={<Trans>High price</Trans>}
tokenA={currencyA?.symbol} />
tokenB={currencyB?.symbol} </AutoRow>
title={<Trans>Max Price</Trans>}
/>
</RowBetween>
</AutoColumn>
) )
} }
...@@ -13,6 +13,7 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter ...@@ -13,6 +13,7 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter
import { isSupportedChain } from 'constants/chains' import { isSupportedChain } from 'constants/chains'
import usePrevious from 'hooks/usePrevious' import usePrevious from 'hooks/usePrevious'
import { useSingleCallResult } from 'lib/hooks/multicall' import { useSingleCallResult } from 'lib/hooks/multicall'
import { BodyWrapper } from 'pages/AppBody'
import { PositionPageUnsupportedContent } from 'pages/Pool/PositionPage' import { PositionPageUnsupportedContent } from 'pages/Pool/PositionPage'
import { useCallback, useEffect, useMemo, useState } from 'react' import { useCallback, useEffect, useMemo, useState } from 'react'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
...@@ -24,7 +25,7 @@ import { ...@@ -24,7 +25,7 @@ import {
useV3MintActionHandlers, useV3MintActionHandlers,
useV3MintState, useV3MintState,
} from 'state/mint/v3/hooks' } from 'state/mint/v3/hooks'
import { useTheme } from 'styled-components/macro' import styled, { useTheme } from 'styled-components/macro'
import { addressesAreEquivalent } from 'utils/addressesAreEquivalent' import { addressesAreEquivalent } from 'utils/addressesAreEquivalent'
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button' import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button'
...@@ -39,7 +40,7 @@ import { PositionPreview } from '../../components/PositionPreview' ...@@ -39,7 +40,7 @@ import { PositionPreview } from '../../components/PositionPreview'
import RangeSelector from '../../components/RangeSelector' import RangeSelector from '../../components/RangeSelector'
import PresetsButtons from '../../components/RangeSelector/PresetsButtons' import PresetsButtons from '../../components/RangeSelector/PresetsButtons'
import RateToggle from '../../components/RateToggle' import RateToggle from '../../components/RateToggle'
import Row, { AutoRow, RowBetween, RowFixed } from '../../components/Row' import Row, { RowBetween, RowFixed } from '../../components/Row'
import { SwitchLocaleLink } from '../../components/SwitchLocaleLink' import { SwitchLocaleLink } from '../../components/SwitchLocaleLink'
import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal' import TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
import { ZERO_PERCENT } from '../../constants/misc' import { ZERO_PERCENT } from '../../constants/misc'
...@@ -67,20 +68,20 @@ import { Review } from './Review' ...@@ -67,20 +68,20 @@ import { Review } from './Review'
import { import {
CurrencyDropdown, CurrencyDropdown,
DynamicSection, DynamicSection,
HideMedium,
MediumOnly, MediumOnly,
PageWrapper,
ResponsiveTwoColumns, ResponsiveTwoColumns,
RightContainer,
ScrollablePage, ScrollablePage,
StackedContainer,
StackedItem,
StyledInput, StyledInput,
Wrapper, Wrapper,
} from './styled' } from './styled'
const DEFAULT_ADD_IN_RANGE_SLIPPAGE_TOLERANCE = new Percent(50, 10_000) const DEFAULT_ADD_IN_RANGE_SLIPPAGE_TOLERANCE = new Percent(50, 10_000)
const StyledBodyWrapper = styled(BodyWrapper)<{ $hasExistingPosition: boolean }>`
padding: ${({ $hasExistingPosition }) => ($hasExistingPosition ? '10px' : 0)};
max-width: 640px;
`
export default function AddLiquidityWrapper() { export default function AddLiquidityWrapper() {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
if (isSupportedChain(chainId)) { if (isSupportedChain(chainId)) {
...@@ -97,7 +98,12 @@ function AddLiquidity() { ...@@ -97,7 +98,12 @@ function AddLiquidity() {
currencyIdB, currencyIdB,
feeAmount: feeAmountFromUrl, feeAmount: feeAmountFromUrl,
tokenId, tokenId,
} = useParams<{ currencyIdA?: string; currencyIdB?: string; feeAmount?: string; tokenId?: string }>() } = useParams<{
currencyIdA?: string
currencyIdB?: string
feeAmount?: string
tokenId?: string
}>()
const { account, chainId, provider } = useWeb3React() const { account, chainId, provider } = useWeb3React()
const theme = useTheme() const theme = useTheme()
...@@ -600,7 +606,7 @@ function AddLiquidity() { ...@@ -600,7 +606,7 @@ function AddLiquidity() {
)} )}
pendingText={pendingText} pendingText={pendingText}
/> />
<PageWrapper wide={!hasExistingPosition}> <StyledBodyWrapper $hasExistingPosition={hasExistingPosition}>
<AddRemoveTabs <AddRemoveTabs
creating={false} creating={false}
adding={true} adding={true}
...@@ -611,28 +617,12 @@ function AddLiquidity() { ...@@ -611,28 +617,12 @@ function AddLiquidity() {
{!hasExistingPosition && ( {!hasExistingPosition && (
<Row justifyContent="flex-end" style={{ width: 'fit-content', minWidth: 'fit-content' }}> <Row justifyContent="flex-end" style={{ width: 'fit-content', minWidth: 'fit-content' }}>
<MediumOnly> <MediumOnly>
<ButtonText onClick={clearAll} margin="0 15px 0 0"> <ButtonText onClick={clearAll}>
<ThemedText.DeprecatedBlue fontSize="12px"> <ThemedText.DeprecatedBlue fontSize="12px">
<Trans>Clear All</Trans> <Trans>Clear All</Trans>
</ThemedText.DeprecatedBlue> </ThemedText.DeprecatedBlue>
</ButtonText> </ButtonText>
</MediumOnly> </MediumOnly>
{baseCurrency && quoteCurrency ? (
<RateToggle
currencyA={baseCurrency}
currencyB={quoteCurrency}
handleRateToggle={() => {
if (!ticksAtLimit[Bound.LOWER] && !ticksAtLimit[Bound.UPPER]) {
onLeftRangeInput((invertPrice ? priceLower : priceUpper?.invert())?.toSignificant(6) ?? '')
onRightRangeInput((invertPrice ? priceUpper : priceLower?.invert())?.toSignificant(6) ?? '')
onFieldAInput(formattedAmounts[Field.CURRENCY_B] ?? '')
}
navigate(
`/add/${currencyIdB as string}/${currencyIdA as string}${feeAmount ? '/' + feeAmount : ''}`
)
}}
/>
) : null}
</Row> </Row>
)} )}
</AddRemoveTabs> </AddRemoveTabs>
...@@ -698,10 +688,190 @@ function AddLiquidity() { ...@@ -698,10 +688,190 @@ function AddLiquidity() {
/> />
)} )}
</AutoColumn> </AutoColumn>
{!hasExistingPosition && (
<>
<DynamicSection gap="md" disabled={!feeAmount || invalidPool}>
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Price Range</Trans>
</ThemedText.DeprecatedLabel>
{Boolean(baseCurrency && quoteCurrency) && (
<RowFixed gap="8px">
<PresetsButtons onSetFullRange={handleSetFullRange} />
<RateToggle
currencyA={baseCurrency as Currency}
currencyB={quoteCurrency as Currency}
handleRateToggle={() => {
if (!ticksAtLimit[Bound.LOWER] && !ticksAtLimit[Bound.UPPER]) {
onLeftRangeInput(
(invertPrice ? priceLower : priceUpper?.invert())?.toSignificant(6) ?? ''
)
onRightRangeInput(
(invertPrice ? priceUpper : priceLower?.invert())?.toSignificant(6) ?? ''
)
onFieldAInput(formattedAmounts[Field.CURRENCY_B] ?? '')
}
navigate(
`/add/${currencyIdB as string}/${currencyIdA as string}${
feeAmount ? '/' + feeAmount : ''
}`
)
}}
/>
</RowFixed>
)}
</RowBetween>
<RangeSelector
priceLower={priceLower}
priceUpper={priceUpper}
getDecrementLower={getDecrementLower}
getIncrementLower={getIncrementLower}
getDecrementUpper={getDecrementUpper}
getIncrementUpper={getIncrementUpper}
onLeftRangeInput={onLeftRangeInput}
onRightRangeInput={onRightRangeInput}
currencyA={baseCurrency}
currencyB={quoteCurrency}
feeAmount={feeAmount}
ticksAtLimit={ticksAtLimit}
/>
{outOfRange && (
<YellowCard padding="8px 12px" $borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.deprecated_yellow3} size="16px" />
<ThemedText.DeprecatedYellow ml="12px" fontSize="12px">
<Trans>
Your position will not earn fees or be used in trades until the market price moves into
your range.
</Trans>
</ThemedText.DeprecatedYellow>
</RowBetween>
</YellowCard>
)}
{invalidRange && (
<YellowCard padding="8px 12px" $borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.deprecated_yellow3} size="16px" />
<ThemedText.DeprecatedYellow ml="12px" fontSize="12px">
<Trans>Invalid range selected. The min price must be lower than the max price.</Trans>
</ThemedText.DeprecatedYellow>
</RowBetween>
</YellowCard>
)}
</DynamicSection>
<DynamicSection gap="md" disabled={!feeAmount || invalidPool}>
{!noLiquidity ? (
<>
{Boolean(price && baseCurrency && quoteCurrency && !noLiquidity) && (
<AutoColumn gap="2px" style={{ marginTop: '0.5rem' }}>
<Trans>
<ThemedText.DeprecatedMain fontWeight={500} fontSize={12} color="text1">
Current Price:
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedBody fontWeight={500} fontSize={20} color="text1">
{price && (
<HoverInlineText
maxCharacters={20}
text={invertPrice ? price.invert().toSignificant(6) : price.toSignificant(6)}
/>
)}
</ThemedText.DeprecatedBody>
{baseCurrency && (
<ThemedText.DeprecatedBody color="text2" fontSize={12}>
{quoteCurrency?.symbol} per {baseCurrency.symbol}
</ThemedText.DeprecatedBody>
)}
</Trans>
</AutoColumn>
)}
<LiquidityChartRangeInput
currencyA={baseCurrency ?? undefined}
currencyB={quoteCurrency ?? undefined}
feeAmount={feeAmount}
ticksAtLimit={ticksAtLimit}
price={
price ? parseFloat((invertPrice ? price.invert() : price).toSignificant(8)) : undefined
}
priceLower={priceLower}
priceUpper={priceUpper}
onLeftRangeInput={onLeftRangeInput}
onRightRangeInput={onRightRangeInput}
interactive={!hasExistingPosition}
/>
</>
) : (
<AutoColumn gap="md">
{noLiquidity && (
<BlueCard
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
padding: '1rem 1rem',
}}
>
<ThemedText.DeprecatedBody
fontSize={14}
style={{ fontWeight: 500 }}
textAlign="left"
color={theme.accentAction}
>
<Trans>
This pool must be initialized before you can add liquidity. To initialize, select a
starting price for the pool. Then, enter your liquidity price range and deposit amount.
Gas fees will be higher than usual due to the initialization transaction.
</Trans>
</ThemedText.DeprecatedBody>
</BlueCard>
)}
<OutlineCard padding="12px">
<StyledInput
className="start-price-input"
value={startPriceTypedValue}
onUserInput={onStartPriceInput}
/>
</OutlineCard>
<RowBetween
style={{
backgroundColor: theme.deprecated_bg1,
padding: '12px',
borderRadius: '12px',
}}
>
<ThemedText.DeprecatedMain>
<Trans>Starting {baseCurrency?.symbol} Price:</Trans>
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedMain>
{price ? (
<ThemedText.DeprecatedMain>
<RowFixed>
<HoverInlineText
maxCharacters={20}
text={invertPrice ? price?.invert()?.toSignificant(8) : price?.toSignificant(8)}
/>{' '}
<span style={{ marginLeft: '4px' }}>
{quoteCurrency?.symbol} per {baseCurrency?.symbol}
</span>
</RowFixed>
</ThemedText.DeprecatedMain>
) : (
'-'
)}
</ThemedText.DeprecatedMain>
</RowBetween>
</AutoColumn>
)}
</DynamicSection>
</>
)}
<div> <div>
<DynamicSection <DynamicSection disabled={invalidPool || invalidRange || (noLiquidity && !startPriceTypedValue)}>
disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange}
>
<AutoColumn gap="md"> <AutoColumn gap="md">
<ThemedText.DeprecatedLabel> <ThemedText.DeprecatedLabel>
{hasExistingPosition ? <Trans>Add more liquidity</Trans> : <Trans>Deposit Amounts</Trans>} {hasExistingPosition ? <Trans>Add more liquidity</Trans> : <Trans>Deposit Amounts</Trans>}
...@@ -737,199 +907,10 @@ function AddLiquidity() { ...@@ -737,199 +907,10 @@ function AddLiquidity() {
</AutoColumn> </AutoColumn>
</DynamicSection> </DynamicSection>
</div> </div>
<Buttons />
{!hasExistingPosition ? (
<>
<HideMedium>
<Buttons />
</HideMedium>
<RightContainer gap="lg">
<DynamicSection gap="md" disabled={!feeAmount || invalidPool}>
{!noLiquidity ? (
<>
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Price Range</Trans>
</ThemedText.DeprecatedLabel>
</RowBetween>
{price && baseCurrency && quoteCurrency && !noLiquidity && (
<AutoRow gap="4px" justify="center" style={{ marginTop: '0.5rem' }}>
<Trans>
<ThemedText.DeprecatedMain
fontWeight={500}
textAlign="center"
fontSize={12}
color="text1"
>
Current Price:
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedBody
fontWeight={500}
textAlign="center"
fontSize={12}
color="text1"
>
<HoverInlineText
maxCharacters={20}
text={invertPrice ? price.invert().toSignificant(6) : price.toSignificant(6)}
/>
</ThemedText.DeprecatedBody>
<ThemedText.DeprecatedBody color="text2" fontSize={12}>
{quoteCurrency?.symbol} per {baseCurrency.symbol}
</ThemedText.DeprecatedBody>
</Trans>
</AutoRow>
)}
<LiquidityChartRangeInput
currencyA={baseCurrency ?? undefined}
currencyB={quoteCurrency ?? undefined}
feeAmount={feeAmount}
ticksAtLimit={ticksAtLimit}
price={
price ? parseFloat((invertPrice ? price.invert() : price).toSignificant(8)) : undefined
}
priceLower={priceLower}
priceUpper={priceUpper}
onLeftRangeInput={onLeftRangeInput}
onRightRangeInput={onRightRangeInput}
interactive={!hasExistingPosition}
/>
</>
) : (
<AutoColumn gap="md">
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Starting Price</Trans>
</ThemedText.DeprecatedLabel>
</RowBetween>
{noLiquidity && (
<BlueCard
style={{
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
padding: '1rem 1rem',
}}
>
<ThemedText.DeprecatedBody
fontSize={14}
style={{ fontWeight: 500 }}
textAlign="left"
color={theme.accentAction}
>
<Trans>
This pool must be initialized before you can add liquidity. To initialize, select a
starting price for the pool. Then, enter your liquidity price range and deposit
amount. Gas fees will be higher than usual due to the initialization transaction.
</Trans>
</ThemedText.DeprecatedBody>
</BlueCard>
)}
<OutlineCard padding="12px">
<StyledInput
className="start-price-input"
value={startPriceTypedValue}
onUserInput={onStartPriceInput}
/>
</OutlineCard>
<RowBetween
style={{ backgroundColor: theme.deprecated_bg1, padding: '12px', borderRadius: '12px' }}
>
<ThemedText.DeprecatedMain>
<Trans>Current {baseCurrency?.symbol} Price:</Trans>
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedMain>
{price ? (
<ThemedText.DeprecatedMain>
<RowFixed>
<HoverInlineText
maxCharacters={20}
text={invertPrice ? price?.invert()?.toSignificant(5) : price?.toSignificant(5)}
/>{' '}
<span style={{ marginLeft: '4px' }}>{quoteCurrency?.symbol}</span>
</RowFixed>
</ThemedText.DeprecatedMain>
) : (
'-'
)}
</ThemedText.DeprecatedMain>
</RowBetween>
</AutoColumn>
)}
</DynamicSection>
<DynamicSection
gap="md"
disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}
>
<StackedContainer>
<StackedItem>
<AutoColumn gap="md">
{noLiquidity && (
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Price Range</Trans>
</ThemedText.DeprecatedLabel>
</RowBetween>
)}
<RangeSelector
priceLower={priceLower}
priceUpper={priceUpper}
getDecrementLower={getDecrementLower}
getIncrementLower={getIncrementLower}
getDecrementUpper={getDecrementUpper}
getIncrementUpper={getIncrementUpper}
onLeftRangeInput={onLeftRangeInput}
onRightRangeInput={onRightRangeInput}
currencyA={baseCurrency}
currencyB={quoteCurrency}
feeAmount={feeAmount}
ticksAtLimit={ticksAtLimit}
/>
<PresetsButtons onSetFullRange={handleSetFullRange} />
</AutoColumn>
</StackedItem>
</StackedContainer>
{outOfRange ? (
<YellowCard padding="8px 12px" $borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.deprecated_yellow3} size="16px" />
<ThemedText.DeprecatedYellow ml="12px" fontSize="12px">
<Trans>
Your position will not earn fees or be used in trades until the market price moves into
your range.
</Trans>
</ThemedText.DeprecatedYellow>
</RowBetween>
</YellowCard>
) : null}
{invalidRange ? (
<YellowCard padding="8px 12px" $borderRadius="12px">
<RowBetween>
<AlertTriangle stroke={theme.deprecated_yellow3} size="16px" />
<ThemedText.DeprecatedYellow ml="12px" fontSize="12px">
<Trans>Invalid range selected. The min price must be lower than the max price.</Trans>
</ThemedText.DeprecatedYellow>
</RowBetween>
</YellowCard>
) : null}
</DynamicSection>
<MediumOnly>
<Buttons />
</MediumOnly>
</RightContainer>
</>
) : (
<Buttons />
)}
</ResponsiveTwoColumns> </ResponsiveTwoColumns>
</Wrapper> </Wrapper>
</PageWrapper> </StyledBodyWrapper>
{showOwnershipWarning && <OwnershipWarning ownerAddress={owner} />} {showOwnershipWarning && <OwnershipWarning ownerAddress={owner} />}
{addIsUnsupported && ( {addIsUnsupported && (
<UnsupportedCurrencyFooter <UnsupportedCurrencyFooter
......
import { AutoColumn } from 'components/Column' import { AutoColumn } from 'components/Column'
import CurrencyInputPanel from 'components/CurrencyInputPanel' import CurrencyInputPanel from 'components/CurrencyInputPanel'
import Input from 'components/NumericalInput' import Input from 'components/NumericalInput'
import { BodyWrapper } from 'pages/AppBody'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
export const PageWrapper = styled(BodyWrapper)<{ wide: boolean }>`
max-width: ${({ wide }) => (wide ? '880px' : '480px')};
width: 100%;
padding: ${({ wide }) => (wide ? '10px' : '0')};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
max-width: 480px;
`};
`
export const Wrapper = styled.div` export const Wrapper = styled.div`
position: relative; position: relative;
padding: 26px 16px; padding: 26px 16px;
min-width: 480px;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
min-width: 400px;
`};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToExtraSmall`
min-width: 340px;
`};
` `
export const ScrollablePage = styled.div` export const ScrollablePage = styled.div`
padding: 68px 8px 0px; padding: 20px 8px 0px;
position: relative; position: relative;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
max-width: 480px;
margin: 0 auto; margin: 0 auto;
`}; `};
...@@ -67,56 +45,19 @@ export const StyledInput = styled(Input)` ...@@ -67,56 +45,19 @@ export const StyledInput = styled(Input)`
/* two-column layout where DepositAmount is moved at the very end on mobile. */ /* two-column layout where DepositAmount is moved at the very end on mobile. */
export const ResponsiveTwoColumns = styled.div<{ wide: boolean }>` export const ResponsiveTwoColumns = styled.div<{ wide: boolean }>`
display: grid; display: flex;
grid-column-gap: 50px; flex-direction: column;
grid-row-gap: 15px; gap: 20px;
grid-template-columns: ${({ wide }) => (wide ? '1fr 1fr' : '1fr')};
grid-template-rows: max-content;
grid-auto-flow: row;
padding-top: 20px; padding-top: 20px;
border-top: 1px solid ${({ theme }) => theme.backgroundInteractive}; border-top: 1px solid ${({ theme }) => theme.backgroundInteractive};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
grid-template-columns: 1fr;
margin-top: 0; margin-top: 0;
`}; `};
` `
export const RightContainer = styled(AutoColumn)`
grid-row: 1 / 3;
grid-column: 2;
height: fit-content;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
grid-row: 2 / 3;
grid-column: 1;
`};
`
export const StackedContainer = styled.div`
display: grid;
`
export const StackedItem = styled.div<{ zIndex?: number }>`
grid-column: 1;
grid-row: 1;
height: 100%;
z-index: ${({ zIndex }) => zIndex};
`
export const MediumOnly = styled.div` export const MediumOnly = styled.div`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium` ${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
display: none; display: none;
`}; `};
` `
export const HideMedium = styled.div`
display: none;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
display: block;
`};
`
import React, { PropsWithChildren } from 'react' import { PropsWithChildren } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { Z_INDEX } from 'theme/zIndex' import { Z_INDEX } from 'theme/zIndex'
......
...@@ -12,6 +12,8 @@ import JSBI from 'jsbi' ...@@ -12,6 +12,8 @@ import JSBI from 'jsbi'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount' import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { Wrapper } from 'pages/Pool/styleds' import { Wrapper } from 'pages/Pool/styleds'
import { useCallback, useMemo, useState } from 'react' import { useCallback, useMemo, useState } from 'react'
import { ArrowLeft } from 'react-feather'
import { Link } from 'react-router-dom'
import { import {
CreateProposalData, CreateProposalData,
ProposalState, ProposalState,
...@@ -24,7 +26,6 @@ import { ...@@ -24,7 +26,6 @@ import {
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme' import { ExternalLink, ThemedText } from 'theme'
import { CreateProposalTabs } from '../../components/NavigationTabs'
import { LATEST_GOVERNOR_INDEX } from '../../constants/governance' import { LATEST_GOVERNOR_INDEX } from '../../constants/governance'
import { UNI } from '../../constants/tokens' import { UNI } from '../../constants/tokens'
import AppBody from '../AppBody' import AppBody from '../AppBody'
...@@ -45,6 +46,19 @@ const PageWrapper = styled(AutoColumn)` ...@@ -45,6 +46,19 @@ const PageWrapper = styled(AutoColumn)`
} }
` `
const BackArrow = styled(ArrowLeft)`
cursor: pointer;
color: ${({ theme }) => theme.textPrimary};
`
const Nav = styled(Link)`
align-items: center;
display: flex;
flex-direction: row;
justify-content: flex-start;
margin: 1em 0 0 1em;
text-decoration: none;
`
const CreateProposalButton = ({ const CreateProposalButton = ({
proposalThreshold, proposalThreshold,
hasActiveOrPendingProposal, hasActiveOrPendingProposal,
...@@ -242,7 +256,10 @@ ${bodyValue} ...@@ -242,7 +256,10 @@ ${bodyValue}
<Trace page={InterfacePageName.VOTE_PAGE} shouldLogImpression> <Trace page={InterfacePageName.VOTE_PAGE} shouldLogImpression>
<PageWrapper> <PageWrapper>
<AppBody $maxWidth="800px"> <AppBody $maxWidth="800px">
<CreateProposalTabs /> <Nav to="/vote">
<BackArrow />
<ThemedText.SubHeaderLarge>Create Proposal</ThemedText.SubHeaderLarge>
</Nav>
<CreateProposalWrapper> <CreateProposalWrapper>
<BlueCard> <BlueCard>
<AutoColumn gap="10px"> <AutoColumn gap="10px">
......
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