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: Callil Capuozzo <callil@uniswap.org>
This commit is contained in:
parent
dc2225a2bc
commit
a1b3776686
@ -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,110 +212,99 @@ 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>
|
||||
)}
|
||||
<Container hideInput={hideInput} disabled={!chainAllowed}>
|
||||
<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 />
|
||||
{!locked && (
|
||||
<>
|
||||
<Container hideInput={hideInput} disabled={!chainAllowed}>
|
||||
<InputRow style={hideInput ? { padding: '0', borderRadius: '8px' } : {}} selected={!onCurrencySelect}>
|
||||
{!hideInput && (
|
||||
<StyledNumericalInput
|
||||
className="token-amount-input"
|
||||
value={value}
|
||||
onUserInput={onUserInput}
|
||||
disabled={!chainAllowed}
|
||||
$loading={loading}
|
||||
/>
|
||||
)}
|
||||
</RowBetween>
|
||||
</FiatRow>
|
||||
)}
|
||||
</Container>
|
||||
|
||||
<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" />
|
||||
)}
|
||||
{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 && (
|
||||
<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">
|
||||
<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>
|
||||
)}
|
||||
|
||||
<InputRow>
|
||||
<InputColumn justify="flex-start">
|
||||
<InputTitle fontSize={12} textAlign="center">
|
||||
{title}
|
||||
</InputTitle>
|
||||
<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>
|
||||
</AutoColumn>
|
||||
{!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};
|
||||
|
@ -1,8 +1,7 @@
|
||||
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,37 +40,33 @@ export default function RangeSelector({
|
||||
const rightPrice = isSorted ? priceUpper : priceLower?.invert()
|
||||
|
||||
return (
|
||||
<AutoColumn gap="md">
|
||||
<RowBetween>
|
||||
<StepCounter
|
||||
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(5) ?? ''}
|
||||
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>}
|
||||
tokenA={currencyA?.symbol}
|
||||
tokenB={currencyB?.symbol}
|
||||
/>
|
||||
<StepCounter
|
||||
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '∞' : rightPrice?.toSignificant(5) ?? ''}
|
||||
onUserInput={onRightRangeInput}
|
||||
width="48%"
|
||||
decrement={isSorted ? getDecrementUpper : getIncrementLower}
|
||||
increment={isSorted ? getIncrementUpper : getDecrementLower}
|
||||
incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
|
||||
decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
|
||||
feeAmount={feeAmount}
|
||||
label={rightPrice ? `${currencyB?.symbol}` : '-'}
|
||||
tokenA={currencyA?.symbol}
|
||||
tokenB={currencyB?.symbol}
|
||||
title={<Trans>Max Price</Trans>}
|
||||
/>
|
||||
</RowBetween>
|
||||
</AutoColumn>
|
||||
<AutoRow gap="md">
|
||||
<StepCounter
|
||||
value={ticksAtLimit[isSorted ? Bound.LOWER : Bound.UPPER] ? '0' : leftPrice?.toSignificant(8) ?? ''}
|
||||
onUserInput={onLeftRangeInput}
|
||||
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>Low price</Trans>}
|
||||
tokenA={currencyA?.symbol}
|
||||
tokenB={currencyB?.symbol}
|
||||
/>
|
||||
<StepCounter
|
||||
value={ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER] ? '∞' : rightPrice?.toSignificant(8) ?? ''}
|
||||
onUserInput={onRightRangeInput}
|
||||
decrement={isSorted ? getDecrementUpper : getIncrementLower}
|
||||
increment={isSorted ? getIncrementUpper : getDecrementLower}
|
||||
incrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
|
||||
decrementDisabled={rightPrice === undefined || ticksAtLimit[isSorted ? Bound.UPPER : Bound.LOWER]}
|
||||
feeAmount={feeAmount}
|
||||
label={rightPrice ? `${currencyB?.symbol}` : '-'}
|
||||
tokenA={currencyA?.symbol}
|
||||
tokenB={currencyB?.symbol}
|
||||
title={<Trans>High price</Trans>}
|
||||
/>
|
||||
</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,10 +688,190 @@ function AddLiquidity() {
|
||||
/>
|
||||
)}
|
||||
</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>
|
||||
<DynamicSection
|
||||
disabled={tickLower === undefined || tickUpper === undefined || invalidPool || invalidRange}
|
||||
>
|
||||
<DynamicSection disabled={invalidPool || invalidRange || (noLiquidity && !startPriceTypedValue)}>
|
||||
<AutoColumn gap="md">
|
||||
<ThemedText.DeprecatedLabel>
|
||||
{hasExistingPosition ? <Trans>Add more liquidity</Trans> : <Trans>Deposit Amounts</Trans>}
|
||||
@ -737,199 +907,10 @@ function AddLiquidity() {
|
||||
</AutoColumn>
|
||||
</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' }}>
|
||||
<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 />
|
||||
)}
|
||||
<Buttons />
|
||||
</ResponsiveTwoColumns>
|
||||
</Wrapper>
|
||||
</PageWrapper>
|
||||
</StyledBodyWrapper>
|
||||
{showOwnershipWarning && <OwnershipWarning ownerAddress={owner} />}
|
||||
{addIsUnsupported && (
|
||||
<UnsupportedCurrencyFooter
|
||||
|
@ -1,42 +1,20 @@
|
||||
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;
|
||||
`};
|
||||
`
|
||||
|
@ -1,4 +1,4 @@
|
||||
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">
|
||||
|
Loading…
Reference in New Issue
Block a user