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'
import { Pair } from '@uniswap/v2-sdk'
import { useWeb3React } from '@web3-react/core'
import { TraceEvent } from 'analytics'
import { AutoColumn } from 'components/Column'
import { LoadingOpacityContainer, loadingOpacityMixin } from 'components/Loader/styled'
import { isSupportedChain } from 'constants/chains'
import { darken } from 'polished'
import { ReactNode, useCallback, useState } from 'react'
import { Lock } from 'react-feather'
import styled, { useTheme } from 'styled-components/macro'
import { flexColumnNoWrap, flexRowNoWrap } from 'theme/styles'
import { formatCurrencyAmount } from 'utils/formatCurrencyAmount'
......@@ -36,18 +34,6 @@ const InputPanel = styled.div<{ hideInput?: boolean }>`
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 }>`
border-radius: ${({ hideInput }) => (hideInput ? '16px' : '20px')};
border: 1px solid ${({ theme }) => theme.backgroundSurface};
......@@ -226,16 +212,8 @@ export default function CurrencyInputPanel({
return (
<InputPanel id={id} hideInput={hideInput} {...rest}>
{locked && (
<FixedContainer>
<AutoColumn gap="sm" justify="center">
<Lock />
<ThemedText.DeprecatedLabel fontSize="12px" textAlign="center" padding="0 12px">
<Trans>The market price is outside your specified price range. Single-asset deposit only.</Trans>
</ThemedText.DeprecatedLabel>
</AutoColumn>
</FixedContainer>
)}
{!locked && (
<>
<Container hideInput={hideInput} disabled={!chainAllowed}>
<InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}>
{!hideInput && (
......@@ -267,9 +245,9 @@ export default function CurrencyInputPanel({
<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}
) : (
currency && <CurrencyLogo style={{ marginRight: '0.5rem' }} currency={currency} size="24px" />
)}
{pair ? (
<StyledTokenName className="pair-name-container">
{pair?.token0.symbol}:{pair?.token1.symbol}
......@@ -288,13 +266,13 @@ export default function CurrencyInputPanel({
</Aligner>
</CurrencySelect>
</InputRow>
{!hideInput && !hideBalance && currency && (
{Boolean(!hideInput && !hideBalance && currency) && (
<FiatRow>
<RowBetween>
<LoadingOpacityContainer $loading={loading}>
{fiatValue && <FiatValue fiatValue={fiatValue} />}
</LoadingOpacityContainer>
{account ? (
{account && (
<RowFixed style={{ height: '17px' }}>
<ThemedText.DeprecatedBody
onClick={onMax}
......@@ -303,15 +281,12 @@ export default function CurrencyInputPanel({
fontSize={14}
style={{ display: 'inline', cursor: 'pointer' }}
>
{!hideBalance && currency && selectedCurrencyBalance ? (
renderBalance ? (
renderBalance(selectedCurrencyBalance)
) : (
{Boolean(!hideBalance && currency && selectedCurrencyBalance) &&
(renderBalance?.(selectedCurrencyBalance as CurrencyAmount<Currency>) || (
<Trans>Balance: {formatCurrencyAmount(selectedCurrencyBalance, 4)}</Trans>
)
) : null}
))}
</ThemedText.DeprecatedBody>
{showMaxButton && selectedCurrencyBalance ? (
{Boolean(showMaxButton && selectedCurrencyBalance) && (
<TraceEvent
events={[BrowserEvent.onClick]}
name={SwapEventName.SWAP_MAX_TOKEN_AMOUNT_SELECTED}
......@@ -321,15 +296,15 @@ export default function CurrencyInputPanel({
<Trans>MAX</Trans>
</StyledBalanceMax>
</TraceEvent>
) : null}
)}
</RowFixed>
) : (
<span />
)}
</RowBetween>
</FiatRow>
)}
</Container>
</>
)}
{onCurrencySelect && (
<CurrencySearchModal
isOpen={modalOpen}
......
......@@ -25,9 +25,7 @@ const pulse = (color: string) => keyframes`
`
const InputRow = styled.div`
display: grid;
grid-template-columns: 30px 1fr 30px;
display: flex;
`
const SmallButton = styled(ButtonGray)`
......@@ -43,18 +41,17 @@ const FocusedOutlineCard = styled(OutlineCard)<{ active?: boolean; pulsing?: boo
const StyledInput = styled(NumericalInput)<{ usePercent?: boolean }>`
background-color: transparent;
text-align: center;
width: 100%;
font-weight: 500;
padding: 0 10px;
text-align: left;
width: 100%;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToSmall`
font-size: 16px;
`};
`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToExtraSmall`
font-size: 12px;
`};
const InputColumn = styled(AutoColumn)`
width: 100%;
`
const InputTitle = styled(ThemedText.DeprecatedSmall)`
......@@ -142,20 +139,11 @@ const StepCounter = ({
return (
<FocusedOutlineCard pulsing={pulsing} active={active} onFocus={handleOnFocus} onBlur={handleOnBlur} width={width}>
<AutoColumn gap="6px">
<InputRow>
<InputColumn justify="flex-start">
<InputTitle fontSize={12} textAlign="center">
{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
className="rate-input-0"
value={localValue}
......@@ -165,7 +153,14 @@ const StepCounter = ({
setLocalValue(val)
}}
/>
<InputTitle fontSize={12} textAlign="left">
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
</InputColumn>
<AutoColumn gap="8px">
{!locked && (
<SmallButton data-testid="increment-price-range" onClick={handleIncrement} disabled={incrementDisabled}>
<ButtonLabel disabled={incrementDisabled} fontSize="12px">
......@@ -173,14 +168,15 @@ const StepCounter = ({
</ButtonLabel>
</SmallButton>
)}
</InputRow>
<InputTitle fontSize={12} textAlign="center">
<Trans>
{tokenB} per {tokenA}
</Trans>
</InputTitle>
{!locked && (
<SmallButton data-testid="decrement-price-range" onClick={handleDecrement} disabled={decrementDisabled}>
<ButtonLabel disabled={decrementDisabled} fontSize="12px">
<Minus size={18} />
</ButtonLabel>
</SmallButton>
)}
</AutoColumn>
</InputRow>
</FocusedOutlineCard>
)
}
......
......@@ -12,7 +12,7 @@ const Wrapper = styled.div<{ count: number }>`
grid-gap: 6px;
position: absolute;
top: -75px;
top: -32px;
right: 0;
`
......
......@@ -6,7 +6,7 @@ import Loader from 'components/Icons/LoadingSpinner'
import { format } from 'd3'
import { useColor } from 'hooks/useColor'
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 { batch } from 'react-redux'
import { Bound } from 'state/mint/v3/actions'
......@@ -46,7 +46,8 @@ const ZOOM_LEVELS: Record<FeeAmount, ZoomLevels> = {
const ChartWrapper = styled.div`
position: relative;
width: 100%;
max-height: 200px;
justify-content: center;
align-content: center;
`
......@@ -180,7 +181,7 @@ export default function LiquidityChartRangeInput({
<ChartWrapper>
<Chart
data={{ series: formattedData, current: price }}
dimensions={{ width: 400, height: 200 }}
dimensions={{ width: 560, height: 200 }}
margins={{ top: 10, right: 2, bottom: 20, left: 0 }}
styles={{
area: {
......
......@@ -3,7 +3,7 @@ import { Percent } from '@uniswap/sdk-core'
import { useWeb3React } from '@web3-react/core'
import { ReactNode } from 'react'
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 { useAppDispatch } from 'state/hooks'
import { resetMintState } from 'state/mint/actions'
......@@ -12,7 +12,7 @@ import styled, { useTheme } from 'styled-components/macro'
import { ThemedText } from 'theme'
import { flexRowNoWrap } from 'theme/styles'
import Row, { RowBetween } from '../Row'
import { RowBetween } from '../Row'
import SettingsTab from '../Settings'
const Tabs = styled.div`
......@@ -22,7 +22,7 @@ const Tabs = styled.div`
justify-content: space-evenly;
`
const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>`
const StyledLink = styled(Link)<{ flex?: string }>`
flex: ${({ flex }) => flex ?? 'none'};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
......@@ -31,9 +31,10 @@ const StyledHistoryLink = styled(HistoryLink)<{ flex?: string }>`
`};
`
const ActiveText = styled.div`
font-weight: 500;
font-size: 20px;
const FindPoolTabsText = styled(ThemedText.SubHeaderLarge)`
position: absolute;
left: 50%;
transform: translateX(-50%);
`
const StyledArrowLeft = styled(ArrowLeft)`
......@@ -44,17 +45,22 @@ export function FindPoolTabs({ origin }: { origin: string }) {
return (
<Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem', position: 'relative' }}>
<HistoryLink to={origin}>
<Link to={origin}>
<StyledArrowLeft />
</HistoryLink>
<ActiveText style={{ position: 'absolute', left: '50%', transform: 'translateX(-50%)' }}>
</Link>
<FindPoolTabsText>
<Trans>Import V2 Pool</Trans>
</ActiveText>
</FindPoolTabsText>
</RowBetween>
</Tabs>
)
}
const AddRemoveTitleText = styled(ThemedText.SubHeaderLarge)`
flex: 1;
margin: auto;
`
export function AddRemoveTabs({
adding,
creating,
......@@ -83,7 +89,7 @@ export function AddRemoveTabs({
return (
<Tabs>
<RowBetween style={{ padding: '1rem 1rem 0 1rem' }}>
<StyledHistoryLink
<StyledLink
to={poolLink}
onClick={() => {
if (adding) {
......@@ -95,12 +101,8 @@ export function AddRemoveTabs({
flex={children ? '1' : undefined}
>
<StyledArrowLeft stroke={theme.textSecondary} />
</StyledHistoryLink>
<ThemedText.DeprecatedMediumHeader
fontWeight={500}
fontSize={20}
style={{ flex: '1', margin: 'auto', textAlign: children ? 'start' : 'center' }}
>
</StyledLink>
<AddRemoveTitleText textAlign={children ? 'start' : 'center'}>
{creating ? (
<Trans>Create a pair</Trans>
) : adding ? (
......@@ -108,23 +110,10 @@ export function AddRemoveTabs({
) : (
<Trans>Remove Liquidity</Trans>
)}
</ThemedText.DeprecatedMediumHeader>
<Box style={{ marginRight: '.5rem' }}>{children}</Box>
</AddRemoveTitleText>
{children && <Box style={{ marginRight: '.5rem' }}>{children}</Box>}
<SettingsTab autoSlippage={autoSlippage} chainId={chainId} />
</RowBetween>
</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'
import { ThemedText } from 'theme'
const Button = styled(ButtonOutlined).attrs(() => ({
padding: '8px',
padding: '6px',
$borderRadius: '8px',
}))`
color: ${({ theme }) => theme.textPrimary};
......
import { Trans } from '@lingui/macro'
import { Currency, Price, Token } from '@uniswap/sdk-core'
import { AutoColumn } from 'components/Column'
import StepCounter from 'components/InputStepCounter/InputStepCounter'
import { RowBetween } from 'components/Row'
import { AutoRow } from 'components/Row'
import { Bound } from 'state/mint/v3/actions'
// currencyA is the base token
......@@ -41,26 +40,23 @@ export default function RangeSelector({
const rightPrice = isSorted ? priceUpper : priceLower?.invert()
return (
<AutoColumn gap="md">
<RowBetween>
<AutoRow gap="md">
<StepCounter
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(5) ?? ''}
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(8) ?? ''}
onUserInput={onLeftRangeInput}
width="48%"
decrement={isSorted ? getDecrementLower : getIncrementUpper}
increment={isSorted ? getIncrementLower : getDecrementUpper}
decrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
incrementDisabled={leftPrice === undefined || ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER]}
feeAmount={feeAmount}
label={leftPrice ? `${currencyB?.symbol}` : '-'}
title={<Trans>Min Price</Trans>}
title={<Trans>Low price</Trans>}
tokenA={currencyA?.symbol}
tokenB={currencyB?.symbol}
/>
<StepCounter
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(5) ?? ''}
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '' : rightPrice?.toSignificant(8) ?? ''}
onUserInput={onRightRangeInput}
width="48%"
decrement={isSorted ? getDecrementUpper : getIncrementLower}
increment={isSorted ? getIncrementUpper : getDecrementLower}
incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
......@@ -69,9 +65,8 @@ export default function RangeSelector({
label={rightPrice ? `${currencyB?.symbol}` : '-'}
tokenA={currencyA?.symbol}
tokenB={currencyB?.symbol}
title={<Trans>Max Price</Trans>}
title={<Trans>High price</Trans>}
/>
</RowBetween>
</AutoColumn>
</AutoRow>
)
}
......@@ -13,6 +13,7 @@ import UnsupportedCurrencyFooter from 'components/swap/UnsupportedCurrencyFooter
import { isSupportedChain } from 'constants/chains'
import usePrevious from 'hooks/usePrevious'
import { useSingleCallResult } from 'lib/hooks/multicall'
import { BodyWrapper } from 'pages/AppBody'
import { PositionPageUnsupportedContent } from 'pages/Pool/PositionPage'
import { useCallback, useEffect, useMemo, useState } from 'react'
import { AlertTriangle } from 'react-feather'
......@@ -24,7 +25,7 @@ import {
useV3MintActionHandlers,
useV3MintState,
} from 'state/mint/v3/hooks'
import { useTheme } from 'styled-components/macro'
import styled, { useTheme } from 'styled-components/macro'
import { addressesAreEquivalent } from 'utils/addressesAreEquivalent'
import { ButtonError, ButtonLight, ButtonPrimary, ButtonText } from '../../components/Button'
......@@ -39,7 +40,7 @@ import { PositionPreview } from '../../components/PositionPreview'
import RangeSelector from '../../components/RangeSelector'
import PresetsButtons from '../../components/RangeSelector/PresetsButtons'
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 TransactionConfirmationModal, { ConfirmationModalContent } from '../../components/TransactionConfirmationModal'
import { ZERO_PERCENT } from '../../constants/misc'
......@@ -67,20 +68,20 @@ import { Review } from './Review'
import {
CurrencyDropdown,
DynamicSection,
HideMedium,
MediumOnly,
PageWrapper,
ResponsiveTwoColumns,
RightContainer,
ScrollablePage,
StackedContainer,
StackedItem,
StyledInput,
Wrapper,
} from './styled'
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() {
const { chainId } = useWeb3React()
if (isSupportedChain(chainId)) {
......@@ -97,7 +98,12 @@ function AddLiquidity() {
currencyIdB,
feeAmount: feeAmountFromUrl,
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 theme = useTheme()
......@@ -600,7 +606,7 @@ function AddLiquidity() {
)}
pendingText={pendingText}
/>
<PageWrapper wide={!hasExistingPosition}>
<StyledBodyWrapper $hasExistingPosition={hasExistingPosition}>
<AddRemoveTabs
creating={false}
adding={true}
......@@ -611,28 +617,12 @@ function AddLiquidity() {
{!hasExistingPosition && (
<Row justifyContent="flex-end" style={{ width: 'fit-content', minWidth: 'fit-content' }}>
<MediumOnly>
<ButtonText onClick={clearAll} margin="0 15px 0 0">
<ButtonText onClick={clearAll}>
<ThemedText.DeprecatedBlue fontSize="12px">
<Trans>Clear All</Trans>
</ThemedText.DeprecatedBlue>
</ButtonText>
</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>
)}
</AddRemoveTabs>
......@@ -698,90 +688,108 @@ function AddLiquidity() {
/>
)}
</AutoColumn>
<div>
<DynamicSection
disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange}
>
<AutoColumn gap="md">
{!hasExistingPosition && (
<>
<DynamicSection gap="md" disabled={!feeAmount || invalidPool}>
<RowBetween>
<ThemedText.DeprecatedLabel>
{hasExistingPosition ? <Trans>Add more liquidity</Trans> : <Trans>Deposit Amounts</Trans>}
<Trans>Set Price Range</Trans>
</ThemedText.DeprecatedLabel>
<CurrencyInputPanel
value={formattedAmounts[Field.CURRENCY_A]}
onUserInput={onFieldAInput}
onMax={() => {
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
{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 : ''
}`
)
}}
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
currency={currencies[Field.CURRENCY_A] ?? null}
id="add-liquidity-input-tokena"
fiatValue={currencyAFiat}
showCommonBases
locked={depositADisabled}
/>
</RowFixed>
)}
</RowBetween>
<CurrencyInputPanel
value={formattedAmounts[Field.CURRENCY_B]}
onUserInput={onFieldBInput}
onMax={() => {
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
}}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
fiatValue={currencyBFiat}
currency={currencies[Field.CURRENCY_B] ?? null}
id="add-liquidity-input-tokenb"
showCommonBases
locked={depositBDisabled}
<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}
/>
</AutoColumn>
{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>
</div>
{!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' }}>
{Boolean(price && baseCurrency && quoteCurrency && !noLiquidity) && (
<AutoColumn gap="2px" style={{ marginTop: '0.5rem' }}>
<Trans>
<ThemedText.DeprecatedMain
fontWeight={500}
textAlign="center"
fontSize={12}
color="text1"
>
<ThemedText.DeprecatedMain fontWeight={500} fontSize={12} color="text1">
Current Price:
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedBody
fontWeight={500}
textAlign="center"
fontSize={12}
color="text1"
>
<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>
</AutoRow>
</AutoColumn>
)}
<LiquidityChartRangeInput
currencyA={baseCurrency ?? undefined}
currencyB={quoteCurrency ?? undefined}
......@@ -799,11 +807,6 @@ function AddLiquidity() {
</>
) : (
<AutoColumn gap="md">
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Starting Price</Trans>
</ThemedText.DeprecatedLabel>
</RowBetween>
{noLiquidity && (
<BlueCard
style={{
......@@ -821,8 +824,8 @@ function AddLiquidity() {
>
<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.
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>
......@@ -835,10 +838,14 @@ function AddLiquidity() {
/>
</OutlineCard>
<RowBetween
style={{ backgroundColor: theme.deprecated_bg1, padding: '12px', borderRadius: '12px' }}
style={{
backgroundColor: theme.deprecated_bg1,
padding: '12px',
borderRadius: '12px',
}}
>
<ThemedText.DeprecatedMain>
<Trans>Current {baseCurrency?.symbol} Price:</Trans>
<Trans>Starting {baseCurrency?.symbol} Price:</Trans>
</ThemedText.DeprecatedMain>
<ThemedText.DeprecatedMain>
{price ? (
......@@ -846,9 +853,11 @@ function AddLiquidity() {
<RowFixed>
<HoverInlineText
maxCharacters={20}
text={invertPrice ? price?.invert()?.toSignificant(5) : price?.toSignificant(5)}
text={invertPrice ? price?.invert()?.toSignificant(8) : price?.toSignificant(8)}
/>{' '}
<span style={{ marginLeft: '4px' }}>{quoteCurrency?.symbol}</span>
<span style={{ marginLeft: '4px' }}>
{quoteCurrency?.symbol} per {baseCurrency?.symbol}
</span>
</RowFixed>
</ThemedText.DeprecatedMain>
) : (
......@@ -859,77 +868,49 @@ function AddLiquidity() {
</AutoColumn>
)}
</DynamicSection>
<DynamicSection
gap="md"
disabled={!feeAmount || invalidPool || (noLiquidity && !startPriceTypedValue)}
>
<StackedContainer>
<StackedItem>
</>
)}
<div>
<DynamicSection disabled={invalidPool || invalidRange || (noLiquidity && !startPriceTypedValue)}>
<AutoColumn gap="md">
{noLiquidity && (
<RowBetween>
<ThemedText.DeprecatedLabel>
<Trans>Set Price Range</Trans>
{hasExistingPosition ? <Trans>Add more liquidity</Trans> : <Trans>Deposit Amounts</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}
<CurrencyInputPanel
value={formattedAmounts[Field.CURRENCY_A]}
onUserInput={onFieldAInput}
onMax={() => {
onFieldAInput(maxAmounts[Field.CURRENCY_A]?.toExact() ?? '')
}}
showMaxButton={!atMaxAmounts[Field.CURRENCY_A]}
currency={currencies[Field.CURRENCY_A] ?? null}
id="add-liquidity-input-tokena"
fiatValue={currencyAFiat}
showCommonBases
locked={depositADisabled}
/>
{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}
<CurrencyInputPanel
value={formattedAmounts[Field.CURRENCY_B]}
onUserInput={onFieldBInput}
onMax={() => {
onFieldBInput(maxAmounts[Field.CURRENCY_B]?.toExact() ?? '')
}}
showMaxButton={!atMaxAmounts[Field.CURRENCY_B]}
fiatValue={currencyBFiat}
currency={currencies[Field.CURRENCY_B] ?? null}
id="add-liquidity-input-tokenb"
showCommonBases
locked={depositBDisabled}
/>
</AutoColumn>
</DynamicSection>
<MediumOnly>
<Buttons />
</MediumOnly>
</RightContainer>
</>
) : (
</div>
<Buttons />
)}
</ResponsiveTwoColumns>
</Wrapper>
</PageWrapper>
</StyledBodyWrapper>
{showOwnershipWarning && <OwnershipWarning ownerAddress={owner} />}
{addIsUnsupported && (
<UnsupportedCurrencyFooter
......
import { AutoColumn } from 'components/Column'
import CurrencyInputPanel from 'components/CurrencyInputPanel'
import Input from 'components/NumericalInput'
import { BodyWrapper } from 'pages/AppBody'
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`
position: relative;
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`
padding: 68px 8px 0px;
padding: 20px 8px 0px;
position: relative;
display: flex;
flex-direction: column;
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
max-width: 480px;
margin: 0 auto;
`};
......@@ -67,56 +45,19 @@ export const StyledInput = styled(Input)`
/* two-column layout where DepositAmount is moved at the very end on mobile. */
export const ResponsiveTwoColumns = styled.div<{ wide: boolean }>`
display: grid;
grid-column-gap: 50px;
grid-row-gap: 15px;
grid-template-columns: ${({ wide }) => (wide ? '1fr 1fr' : '1fr')};
grid-template-rows: max-content;
grid-auto-flow: row;
display: flex;
flex-direction: column;
gap: 20px;
padding-top: 20px;
border-top: 1px solid ${({ theme }) => theme.backgroundInteractive};
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
grid-template-columns: 1fr;
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`
${({ theme }) => theme.deprecated_mediaWidth.deprecated_upToMedium`
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 { Z_INDEX } from 'theme/zIndex'
......
......@@ -12,6 +12,8 @@ import JSBI from 'jsbi'
import tryParseCurrencyAmount from 'lib/utils/tryParseCurrencyAmount'
import { Wrapper } from 'pages/Pool/styleds'
import { useCallback, useMemo, useState } from 'react'
import { ArrowLeft } from 'react-feather'
import { Link } from 'react-router-dom'
import {
CreateProposalData,
ProposalState,
......@@ -24,7 +26,6 @@ import {
import styled from 'styled-components/macro'
import { ExternalLink, ThemedText } from 'theme'
import { CreateProposalTabs } from '../../components/NavigationTabs'
import { LATEST_GOVERNOR_INDEX } from '../../constants/governance'
import { UNI } from '../../constants/tokens'
import AppBody from '../AppBody'
......@@ -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 = ({
proposalThreshold,
hasActiveOrPendingProposal,
......@@ -242,7 +256,10 @@ ${bodyValue}
<Trace page={InterfacePageName.VOTE_PAGE} shouldLogImpression>
<PageWrapper>
<AppBody $maxWidth="800px">
<CreateProposalTabs />
<Nav to="/vote">
<BackArrow />
<ThemedText.SubHeaderLarge>Create Proposal</ThemedText.SubHeaderLarge>
</Nav>
<CreateProposalWrapper>
<BlueCard>
<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