Commit e43d9e03 authored by ianlapham's avatar ianlapham

add popups to context

parent 35d39840
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 13C12.5523 13 13 12.5523 13 12C13 11.4477 12.5523 11 12 11C11.4477 11 11 11.4477 11 12C11 12.5523 11.4477 13 12 13Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19 13C19.5523 13 20 12.5523 20 12C20 11.4477 19.5523 11 19 11C18.4477 11 18 11.4477 18 12C18 12.5523 18.4477 13 19 13Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M5 13C5.55228 13 6 12.5523 6 12C6 11.4477 5.55228 11 5 11C4.44772 11 4 11.4477 4 12C4 12.5523 4.44772 13 5 13Z" stroke="black" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
......@@ -7,6 +7,7 @@ const Card = styled(Box)`
padding: 1rem;
padding: ${({ padding }) => padding};
border: ${({ border }) => border};
border-radius: ${({ borderRadius }) => borderRadius};
`
export default Card
......
import React from 'react'
import styled from 'styled-components'
import Menu from '../Menu'
import Logo from '../../assets/svg/logo.svg'
import Row from '../Row'
import Web3Status from '../Web3Status'
import { CloseIcon } from '../../theme/components'
import { Link } from '../../theme'
import { Text } from 'rebass'
import Card from '../Card'
import { X } from 'react-feather'
import Logo from '../../assets/svg/logo.svg'
import { WETH } from '@uniswap/sdk'
import { isMobile } from 'react-device-detect'
import { useWeb3React } from '../../hooks'
import { useAddressBalance } from '../../contexts/Balances'
import { useWalletModalToggle, usePopups } from '../../contexts/Application'
const HeaderFrame = styled.div`
display: flex;
......@@ -39,13 +51,53 @@ const TitleText = styled.div`
margin-left: 12px;
`
const AccountElement = styled.div`
display: flex;
min-width: 0;
display: flex;
flex-direction: row;
align-items: center;
background-color: ${({ theme }) => theme.outlineGrey};
border: 1px solid ${({ theme }) => theme.outlineGrey};
border-radius: 8px;
padding-left: 8px;
:focus {
border: 1px solid blue;
}
/* width: 100%; */
`
const FixedPopupColumn = styled.div`
position: absolute;
top: 80px;
right: 20px
width: 340px;
`
const StyledClose = styled(X)`
position: absolute;
right: 10px;
:hover {
cursor: pointer;
}
`
export default function Header() {
const { account, chainId } = useWeb3React()
const userEthBalance = useAddressBalance(account, WETH[chainId])
const toggleWalletModal = useWalletModalToggle()
const [activePopups, , removePopup] = usePopups()
return (
<HeaderFrame>
<HeaderElement>
<Title>
<Link id="link" href="https://uniswap.io">
<img src={Logo} />
<img src={Logo} alt="logo" />
</Link>
<Link id="link" href="https://uniswap.io">
<TitleText>Uniswap</TitleText>
......@@ -53,8 +105,28 @@ export default function Header() {
</Title>
</HeaderElement>
<HeaderElement>
<Web3Status />
<AccountElement>
{!isMobile ? (
<Row style={{ marginRight: '-1.25rem', paddingRight: '1.75rem' }}>
<Text fontWeight={500}> {userEthBalance && userEthBalance?.toFixed(4) + ' ETH'}</Text>
</Row>
) : (
''
)}
<Web3Status onClick={toggleWalletModal} />
</AccountElement>
<Menu />
</HeaderElement>
<FixedPopupColumn>
{activePopups.map(item => {
return (
<Card bg="white" padding={'16px'} key={item.key} borderRadius={'8px'}>
<StyledClose color="#888D9B" onClick={() => removePopup(item.key)} />
{item.content}
</Card>
)
})}
</FixedPopupColumn>
</HeaderFrame>
)
}
import React, { useRef, useEffect, useState } from 'react'
import styled from 'styled-components'
import { useDarkModeManager } from '../../contexts/LocalStorage'
import { ReactComponent as MenuIcon } from '../../assets/images/menu.svg'
import { Link } from '../../theme'
import { darken, transparentize } from 'polished'
import { useAdvancedManager } from '../../contexts/LocalStorage'
import Toggle from 'react-switch'
import { useToggle } from '../../hooks'
const StyledMenuIcon = styled(MenuIcon)`
path {
stroke: ${({ theme }) => theme.textColor};
}
`
const StyledMenuButton = styled.button`
width: 100%;
height: 100%;
border: none;
background-color: transparent;
margin: 0;
padding: 0;
height: 35px;
background-color: ${({ theme }) => theme.outlineGrey};
border: 1px solid ${({ theme }) => theme.outlineGrey};
padding: 0.15rem 0.5rem;
border-radius: 0.5rem;
:hover, :focus {
/* background-color: ${({ theme }) => darken(0.2, theme.concreteGray)}; */
border: 1px solid ${({ theme }) => darken(0.2, theme.concreteGray)};
cursor: pointer;
outline: none;
}
svg {
width: 25px;
height: 24px;
}
`
const StyledMenu = styled.div`
margin-left: 0.5rem;
display: flex;
box-sizing: border-box;
justify-content: center;
align-items: center;
position: relative;
border: none;
text-align: left;
`
const MenuFlyout = styled.span`
min-width: 8.125rem;
background-color: ${({ theme }) => theme.inputBackground};
${({ theme }) => theme.dropShadow}
border: 1px solid ${({ theme }) => theme.mercuryGray};
border-radius: 0.5rem;
padding: 0.5rem;
display: flex;
flex-direction: column;
font-size: 1rem;
position: absolute;
top: 3rem;
right: 0rem;
`
const MenuItem = styled(Link)`
flex: 1;
/* text-align: right; */
padding: 0.5rem 0.5rem;
color: ${({ theme }) => theme.doveGray};
:hover {
color: ${({ theme }) => theme.textColor};
cursor: pointer;
}
`
const ToggleItem = styled.span`
color: ${({ theme }) => theme.doveGray};
padding: 0.5rem 0.5rem 0.5rem 0.5rem;
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
width: 100%;
`
const Divider = styled.span`
width: 100%;
margin-bottom: 0.5rem;
padding-top: 0.5rem;
border-bottom: 1px solid ${({ theme }) => theme.mercuryGray};
`
const StyledToggle = styled(Toggle)`
margin-right: 0.75rem;
.react-switch-bg[style] {
background-color: ${({ theme, checked, showColor }) =>
checked ? theme.connectedGreen : darken(0.05, theme.inputBackground)} !important;
border: 1px solid ${({ theme }) => theme.concreteGray} !important;
}
.react-switch-handle[style] {
background-color: ${({ theme }) => theme.connectedGreen};
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.93, theme.shadowColor)};
border: 1px solid ${({ theme }) => theme.mercuryGray};
border-color: ${({ theme }) => theme.mercuryGray} !important;
top: 2px !important;
margin-left: 1px;
}
`
const StyledToggleNoColor = styled(Toggle)`
margin-right: 0.75rem;
.react-switch-bg[style] {
background-color: ${({ theme }) => darken(0.05, theme.inputBackground)} !important;
border: 1px solid ${({ theme }) => theme.concreteGray} !important;
}
.react-switch-handle[style] {
background-color: ${({ theme }) => theme.connectedGreen};
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.93, theme.shadowColor)};
border: 1px solid ${({ theme }) => theme.mercuryGray};
border-color: ${({ theme }) => theme.mercuryGray} !important;
top: 2px !important;
margin-left: 1px;
}
`
const EmojiToggle = styled.span`
font-family: Arial sans-serif;
vertical-align: middle;
text-align: center;
width: 100%;
`
export default function Menu() {
const [isDark, toggleDarkMode] = useDarkModeManager()
const [isAdvanced, toggleAdvanced] = useState()
const node = useRef()
const [open, toggle] = useToggle(false)
useEffect(() => {
const handleClickOutside = e => {
if (node.current.contains(e.target)) {
return
}
toggle()
}
if (open) {
document.addEventListener('mousedown', handleClickOutside)
} else {
document.removeEventListener('mousedown', handleClickOutside)
}
return () => {
document.removeEventListener('mousedown', handleClickOutside)
}
}, [open, toggle])
return (
<StyledMenu ref={node}>
<StyledMenuButton onClick={() => toggle()}>
<StyledMenuIcon />
</StyledMenuButton>
{open ? (
<MenuFlyout>
<MenuItem id="link" href="https://uniswap.io/">
About
</MenuItem>
<MenuItem id="link" href="https://docs.uniswap.io/">
Docs
</MenuItem>
<MenuItem id="link" href="https://github.com/Uniswap">
Code
</MenuItem>
<MenuItem id="link" href="https://uniswap.info/">
Stats
</MenuItem>
<Divider></Divider>
<ToggleItem>
<span>Theme</span>
<StyledToggleNoColor
checked={!isDark}
uncheckedIcon={
<EmojiToggle role="img" aria-label="moon">
{/* eslint-disable-line jsx-a11y/accessible-emoji */}
🌙️
</EmojiToggle>
}
checkedIcon={
<EmojiToggle role="img" aria-label="sun">
{/* eslint-disable-line jsx-a11y/accessible-emoji */}
{'☀️'}
</EmojiToggle>
}
onChange={() => toggleDarkMode()}
/>
</ToggleItem>
<ToggleItem>
<span>Advanced</span>
<StyledToggle
checked={isAdvanced}
uncheckedIcon={false}
checkedIcon={false}
onChange={() => toggleAdvanced()}
/>
</ToggleItem>
</MenuFlyout>
) : (
''
)}
</StyledMenu>
)
}
import React, { useState } from 'react'
import { withRouter } from 'react-router-dom'
import { JSBI } from '@uniswap/sdk'
import { withRouter } from 'react-router-dom'
import { useWeb3React } from '@web3-react/core'
import { useToken } from '../../contexts/Tokens'
import { useExchange } from '../../contexts/Exchanges'
import { useWeb3React } from '@web3-react/core'
import { useAddressBalance } from '../../contexts/Balances'
import { usePopups } from '../../contexts/Application'
import { LightCard } from '../Card'
import PositionCard from '../PositionCard'
import SearchModal from '../SearchModal'
import Row from '../Row'
import TokenLogo from '../TokenLogo'
import SearchModal from '../SearchModal'
import PositionCard from '../PositionCard'
import { Link } from '../../theme'
import { Text } from 'rebass'
import { AutoColumn, ColumnCenter } from '../Column'
import { Plus } from 'react-feather'
import { LightCard } from '../Card'
import { AutoColumn, ColumnCenter } from '../Column'
import { ButtonPrimary, ButtonDropwdown, ButtonDropwdownLight } from '../Button'
import TokenLogo from '../TokenLogo'
import DoubleTokenLogo from '../DoubleLogo'
function PoolFinder({ history }) {
const Fields = {
......@@ -28,6 +30,8 @@ function PoolFinder({ history }) {
const [showSearch, setShowSearch] = useState(false)
const [activeField, setActiveField] = useState(Fields.TOKEN0)
const [, addPopup] = usePopups()
const [token0Address, setToken0Address] = useState()
const [token1Address, setToken1Address] = useState()
......@@ -42,6 +46,18 @@ function PoolFinder({ history }) {
const allowImport = position && JSBI.greaterThan(position.raw, JSBI.BigInt(0))
function endSearch() {
history.goBack()
addPopup(
<Row>
<DoubleTokenLogo a0={token0Address || ''} a1={token1Address || ''} margin={true} />
<Text color="grey">
UNI {token0?.symbol} / {token1?.symbol} pool imported.
</Text>
</Row>
)
}
return (
<>
<AutoColumn gap="24px">
......@@ -144,7 +160,7 @@ function PoolFinder({ history }) {
Liquidity Found!
</Text>
)}
<ButtonPrimary disabled={!allowImport} onClick={() => history.goBack()}>
<ButtonPrimary disabled={!allowImport} onClick={endSearch}>
<Text fontWeight={500} fontSize={20}>
Import
</Text>
......
......@@ -398,7 +398,7 @@ function SearchModal({ history, isOpen, onDismiss, onTokenSelect, urlAddedTokens
<PaddedColumn gap="20px">
<RowBetween>
<Text fontWeight={500} fontSize={16}>
{filterType === 'tokens' ? 'Find A Token' : 'Find A Pool'}
{filterType === 'tokens' ? 'Select A Token' : 'Select A Pool'}
</Text>
<CloseIcon onClick={onDismiss} />
</RowBetween>
......
......@@ -26,7 +26,7 @@ const Web3StatusGeneric = styled.button`
font-size: 0.9rem;
align-items: center;
padding: 0.5rem;
border-radius: 2rem;
border-radius: 10px;
box-sizing: border-box;
cursor: pointer;
user-select: none;
......
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect } from 'react'
import React, { createContext, useContext, useReducer, useMemo, useCallback, useEffect, useState } from 'react'
import { useWeb3React } from '../hooks'
import { safeAccess } from '../utils'
......@@ -6,10 +6,13 @@ import { safeAccess } from '../utils'
const BLOCK_NUMBER = 'BLOCK_NUMBER'
const USD_PRICE = 'USD_PRICE'
const WALLET_MODAL_OPEN = 'WALLET_MODAL_OPEN'
const POPUP_LIST = 'POPUP_LIST'
const UPDATE_BLOCK_NUMBER = 'UPDATE_BLOCK_NUMBER'
const TOGGLE_WALLET_MODAL = 'TOGGLE_WALLET_MODAL'
const ADD_POPUP = 'ADD_POPUP'
const ApplicationContext = createContext()
function useApplicationContext() {
......@@ -32,6 +35,12 @@ function reducer(state, { type, payload }) {
case TOGGLE_WALLET_MODAL: {
return { ...state, [WALLET_MODAL_OPEN]: !state[WALLET_MODAL_OPEN] }
}
case ADD_POPUP: {
const { newList } = payload
return { ...state, [POPUP_LIST]: newList }
}
default: {
throw Error(`Unexpected action type in ApplicationContext reducer: '${type}'.`)
}
......@@ -42,6 +51,7 @@ export default function Provider({ children }) {
const [state, dispatch] = useReducer(reducer, {
[BLOCK_NUMBER]: {},
[USD_PRICE]: {},
[POPUP_LIST]: [],
[WALLET_MODAL_OPEN]: false
})
......@@ -53,12 +63,17 @@ export default function Provider({ children }) {
dispatch({ type: TOGGLE_WALLET_MODAL })
}, [])
const setPopups = useCallback(newList => {
dispatch({ type: ADD_POPUP, payload: { newList } })
}, [])
return (
<ApplicationContext.Provider
value={useMemo(() => [state, { updateBlockNumber, toggleWalletModal }], [
value={useMemo(() => [state, { updateBlockNumber, toggleWalletModal, setPopups }], [
state,
updateBlockNumber,
toggleWalletModal
toggleWalletModal,
setPopups
])}
>
{children}
......@@ -123,3 +138,37 @@ export function useWalletModalToggle() {
return toggleWalletModal
}
export function usePopups() {
const [state, { setPopups }] = useApplicationContext()
const [index, setIndex] = useState(0)
const currentPopups = state[POPUP_LIST]
function addPopup(content) {
const newItem = {
show: true,
key: index,
content: content
}
currentPopups.push(newItem)
setPopups(currentPopups)
setIndex(index + 1)
}
function removePopup(key) {
currentPopups.map(item => {
if (key === item.key) {
item.show = false
}
})
setPopups(currentPopups)
}
const activePopups = currentPopups.filter(item => {
return item.show
})
return [activePopups, addPopup, removePopup]
}
......@@ -9,10 +9,10 @@ import { ChainId, WETH, Token, TokenAmount, Exchange, JSBI } from '@uniswap/sdk'
const UPDATE = 'UPDATE'
const ALL_EXCHANGES: [Token, Token][] = [
[
INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY][WETH[ChainId.RINKEBY].address],
INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY]['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735']
]
// [
// INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY][WETH[ChainId.RINKEBY].address],
// INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY]['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735']
// ]
// [
// INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY]['0xc7AD46e0b8a400Bb3C915120d284AafbA8fc4735'],
// INITIAL_TOKENS_CONTEXT[ChainId.RINKEBY]['0x8ab15C890E5C03B5F240f2D146e3DF54bEf3Df44']
......
......@@ -261,3 +261,10 @@ export function usePrevious(value) {
// Return previous value (happens before update in useEffect above)
return ref.current
}
export function useToggle(initialState = false) {
const [state, setState] = useState(initialState)
const toggle = useCallback(() => setState(state => !state), [])
return [state, toggle]
}
......@@ -4,7 +4,6 @@ import { BrowserRouter, Redirect, Route, Switch } from 'react-router-dom'
import Web3ReactManager from '../components/Web3ReactManager'
import Header from '../components/Header'
import Footer from '../components/Footer'
import NavigationTabs from '../components/NavigationTabs'
import { isAddress, getAllQueryParams } from '../utils'
......@@ -14,7 +13,7 @@ const Send = lazy(() => import('./Send'))
const Pool = lazy(() => import('./Supply'))
const Add = lazy(() => import('./Supply/AddLiquidity'))
const Remove = lazy(() => import('./Supply/RemoveLiquidity'))
const Find = lazy(() => import('../components/TokenFind'))
const Find = lazy(() => import('../components/PoolFinder'))
const AppWrapper = styled.div`
display: flex;
......@@ -150,9 +149,6 @@ export default function App() {
</Web3ReactManager>
</Body>
</BodyWrapper>
<FooterWrapper>
<Footer />
</FooterWrapper>
</AppWrapper>
</Suspense>
</>
......
......@@ -306,9 +306,9 @@ export default function AddLiquidity({ token0, token1 }) {
}, [inputApproval, outputApproval, parsedAmounts])
// errors
const [generalError, setGeneralError] = useState()
const [inputError, setInputError] = useState()
const [outputError, setOutputError] = useState()
const [generalError, setGeneralError] = useState('')
const [inputError, setInputError] = useState('')
const [outputError, setOutputError] = useState('')
const [isValid, setIsValid] = useState(false)
// update errors live
......
......@@ -378,6 +378,7 @@ export default function RemoveLiquidity({ token0, token1 }) {
{ name: 'nonce', type: 'uint256' },
{ name: 'deadline', type: 'uint256' }
]
const message = {
owner: account,
spender: routerAddress,
......
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