Dark theme (#380)
This commit is contained in:
parent
c8f8d838a0
commit
80da6e0ff6
12
src/assets/svg/SVGArrowDown.js
Normal file
12
src/assets/svg/SVGArrowDown.js
Normal file
@ -0,0 +1,12 @@
|
||||
import React from 'react'
|
||||
|
||||
const SVGArrowDown = props => (
|
||||
<svg width="1em" height="1em" viewBox="0 0 9 10" fill="currentColor" {...props}>
|
||||
<path
|
||||
d="M5.298 0H4.24v7.911h-.075L1.256 4.932l-.717.735L4.769 10 9 5.667l-.718-.735-2.908 2.979h-.076V0z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default SVGArrowDown
|
@ -2,17 +2,17 @@ import React, { useState, useEffect } from 'react'
|
||||
import styled from 'styled-components'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useWeb3Context } from 'web3-react'
|
||||
import { lighten } from 'polished'
|
||||
import { transparentize } from 'polished'
|
||||
|
||||
import { isAddress } from '../../utils'
|
||||
import { useDebounce } from '../../hooks'
|
||||
|
||||
const InputPanel = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
box-shadow: 0 4px 8px 0 ${({ theme }) => lighten(0.9, theme.royalBlue)};
|
||||
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.royalBlue)};
|
||||
position: relative;
|
||||
border-radius: 1.25rem;
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
z-index: 1;
|
||||
`
|
||||
|
||||
@ -21,9 +21,10 @@ const ContainerRow = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: 0 0 0 1px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
transition: box-shadow 200ms ease-in-out;
|
||||
border: 1px solid ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
transition: box-shadow 125ms ease-in-out;
|
||||
`
|
||||
|
||||
const InputContainer = styled.div`
|
||||
@ -59,13 +60,15 @@ const Input = styled.input`
|
||||
border: none;
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
|
||||
color: ${({ error, theme }) => (error ? theme.salmonRed : theme.royalBlue)};
|
||||
transition: color 200ms ease-in-out;
|
||||
transition: color 125ms ease-in-out;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
::placeholder {
|
||||
color: ${({ theme }) => theme.chaliceGray};
|
||||
color: ${({ theme }) => theme.placeholderGray};
|
||||
}
|
||||
`
|
||||
|
||||
@ -93,8 +96,9 @@ export default function AddressInputPanel({ title, initialInput = '', onChange =
|
||||
let stale = false
|
||||
|
||||
if (isAddress(debouncedInput)) {
|
||||
try {
|
||||
library.lookupAddress(debouncedInput).then(name => {
|
||||
library
|
||||
.lookupAddress(debouncedInput)
|
||||
.then(name => {
|
||||
if (!stale) {
|
||||
// if an ENS name exists, set it as the destination
|
||||
if (name) {
|
||||
@ -105,14 +109,15 @@ export default function AddressInputPanel({ title, initialInput = '', onChange =
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch {
|
||||
setData({ address: debouncedInput, name: '' })
|
||||
setError(null)
|
||||
}
|
||||
.catch(() => {
|
||||
setData({ address: debouncedInput, name: '' })
|
||||
setError(null)
|
||||
})
|
||||
} else {
|
||||
if (debouncedInput !== '') {
|
||||
try {
|
||||
library.resolveName(debouncedInput).then(address => {
|
||||
library
|
||||
.resolveName(debouncedInput)
|
||||
.then(address => {
|
||||
if (!stale) {
|
||||
// if the debounced input name resolves to an address
|
||||
if (address) {
|
||||
@ -123,9 +128,9 @@ export default function AddressInputPanel({ title, initialInput = '', onChange =
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch {
|
||||
setError(true)
|
||||
}
|
||||
.catch(() => {
|
||||
setError(true)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,8 +2,8 @@ import React, { Component } from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import DropdownBlue from '../../assets/images/dropdown-blue.svg'
|
||||
import DropupBlue from '../../assets/images/dropup-blue.svg'
|
||||
import { ReactComponent as Dropup } from '../../assets/images/dropup-blue.svg'
|
||||
import { ReactComponent as Dropdown } from '../../assets/images/dropdown-blue.svg'
|
||||
|
||||
const SummaryWrapper = styled.div`
|
||||
color: ${({ error, theme }) => (error ? theme.salmonRed : theme.doveGray)};
|
||||
@ -14,7 +14,7 @@ const SummaryWrapper = styled.div`
|
||||
`
|
||||
|
||||
const Details = styled.div`
|
||||
background-color: ${({ theme }) => theme.concreteGray};
|
||||
background-color: ${({ theme }) => theme.doveGray};
|
||||
padding: 1.5rem;
|
||||
border-radius: 1rem;
|
||||
font-size: 0.75rem;
|
||||
@ -42,6 +42,20 @@ const SummaryWrapperContainer = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
const WrappedDropup = ({ isError, highSlippageWarning, ...rest }) => <Dropup {...rest} />
|
||||
const ColoredDropup = styled(WrappedDropup)`
|
||||
path {
|
||||
stroke: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
`
|
||||
|
||||
const WrappedDropdown = ({ isError, highSlippageWarning, ...rest }) => <Dropdown {...rest} />
|
||||
const ColoredDropdown = styled(WrappedDropdown)`
|
||||
path {
|
||||
stroke: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
`
|
||||
|
||||
class ContextualInfo extends Component {
|
||||
static propTypes = {
|
||||
openDetailsText: PropTypes.string,
|
||||
@ -89,12 +103,12 @@ class ContextualInfo extends Component {
|
||||
{!this.state.showDetails ? (
|
||||
<>
|
||||
<span>{openDetailsText}</span>
|
||||
<img src={DropdownBlue} alt="dropdown" />
|
||||
<ColoredDropup />
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<span>{closeDetailsText}</span>
|
||||
<img src={DropupBlue} alt="dropup" />
|
||||
<ColoredDropdown />
|
||||
</>
|
||||
)}
|
||||
</SummaryWrapperContainer>
|
||||
|
@ -61,7 +61,7 @@ const ErrorSpan = styled.span`
|
||||
const WrappedDropup = ({ isError, highSlippageWarning, ...rest }) => <Dropup {...rest} />
|
||||
const ColoredDropup = styled(WrappedDropup)`
|
||||
path {
|
||||
stroke: ${({ isError, theme }) => isError && theme.salmonRed};
|
||||
stroke: ${({ isError, theme }) => (isError ? theme.salmonRed : theme.royalBlue)};
|
||||
|
||||
${({ highSlippageWarning, theme }) =>
|
||||
highSlippageWarning &&
|
||||
@ -74,7 +74,7 @@ const ColoredDropup = styled(WrappedDropup)`
|
||||
const WrappedDropdown = ({ isError, highSlippageWarning, ...rest }) => <Dropdown {...rest} />
|
||||
const ColoredDropdown = styled(WrappedDropdown)`
|
||||
path {
|
||||
stroke: ${({ isError, theme }) => isError && theme.salmonRed};
|
||||
stroke: ${({ isError, theme }) => (isError ? theme.salmonRed : theme.royalBlue)};
|
||||
|
||||
${({ highSlippageWarning, theme }) =>
|
||||
highSlippageWarning &&
|
||||
|
@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import { ethers } from 'ethers'
|
||||
import styled from 'styled-components'
|
||||
import escapeStringRegex from 'escape-string-regexp'
|
||||
import { lighten, darken } from 'polished'
|
||||
import { darken } from 'polished'
|
||||
import Tooltip from '@reach/tooltip'
|
||||
import '@reach/tooltip/styles.css'
|
||||
import { isMobile } from 'react-device-detect'
|
||||
@ -18,6 +18,7 @@ import TokenLogo from '../TokenLogo'
|
||||
import SearchIcon from '../../assets/images/magnifying-glass.svg'
|
||||
import { useTransactionAdder, usePendingApproval } from '../../contexts/Transactions'
|
||||
import { useTokenDetails, useAllTokenDetails } from '../../contexts/Tokens'
|
||||
import { transparentize } from 'polished'
|
||||
|
||||
const GAS_MARGIN = ethers.utils.bigNumberify(1000)
|
||||
|
||||
@ -40,12 +41,14 @@ const SubCurrencySelect = styled.button`
|
||||
const InputRow = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
align-items: center;
|
||||
|
||||
padding: 0.25rem 0.85rem 0.75rem;
|
||||
`
|
||||
|
||||
const Input = styled(BorderlessInput)`
|
||||
font-size: 1.5rem;
|
||||
color: ${({ error, theme }) => error && theme.salmonRed};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
`
|
||||
|
||||
const StyledBorderlessInput = styled(BorderlessInput)`
|
||||
@ -56,7 +59,7 @@ const StyledBorderlessInput = styled(BorderlessInput)`
|
||||
const CurrencySelect = styled.button`
|
||||
align-items: center;
|
||||
font-size: 1rem;
|
||||
color: ${({ selected, theme }) => (selected ? theme.black : theme.royalBlue)};
|
||||
color: ${({ selected, theme }) => (selected ? theme.textColor : theme.royalBlue)};
|
||||
height: 2rem;
|
||||
border: 1px solid ${({ selected, theme }) => (selected ? theme.mercuryGray : theme.royalBlue)};
|
||||
border-radius: 2.5rem;
|
||||
@ -90,27 +93,28 @@ const StyledDropDown = styled(DropDown)`
|
||||
height: 35%;
|
||||
|
||||
path {
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.black : theme.royalBlue)};
|
||||
stroke: ${({ selected, theme }) => (selected ? theme.textColor : theme.royalBlue)};
|
||||
}
|
||||
`
|
||||
|
||||
const InputPanel = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
box-shadow: 0 4px 8px 0 ${({ theme }) => lighten(0.9, theme.royalBlue)};
|
||||
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.royalBlue)};
|
||||
position: relative;
|
||||
border-radius: 1.25rem;
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
z-index: 1;
|
||||
`
|
||||
|
||||
const Container = styled.div`
|
||||
border-radius: 1.25rem;
|
||||
box-shadow: 0 0 0 1px ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
transition: box-shadow 200ms ease-in-out;
|
||||
border: 1px solid ${({ error, theme }) => (error ? theme.salmonRed : theme.mercuryGray)};
|
||||
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
transition: box-shadow 150ms ease-out;
|
||||
|
||||
:focus-within {
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.malibuBlue};
|
||||
border: 1px solid ${({ theme }) => theme.malibuBlue};
|
||||
}
|
||||
`
|
||||
|
||||
@ -145,7 +149,6 @@ const ErrorSpan = styled.span`
|
||||
|
||||
const TokenModal = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
width: 100%;
|
||||
`
|
||||
|
||||
|
@ -10,8 +10,7 @@ import CurrencyInputPanel from '../CurrencyInputPanel'
|
||||
import AddressInputPanel from '../AddressInputPanel'
|
||||
import OversizedPanel from '../OversizedPanel'
|
||||
import TransactionDetails from '../TransactionDetails'
|
||||
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
|
||||
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
|
||||
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
||||
import { amountFormatter, calculateGasMargin } from '../../utils'
|
||||
import { useExchangeContract } from '../../hooks'
|
||||
import { useTokenDetails } from '../../contexts/Tokens'
|
||||
@ -42,7 +41,9 @@ const DownArrowBackground = styled.div`
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const DownArrow = styled.img`
|
||||
const WrappedArrowDown = ({ clickable, active, ...rest }) => <ArrowDown {...rest} />
|
||||
const DownArrow = styled(WrappedArrowDown)`
|
||||
color: ${({ theme, active }) => (active ? theme.royalBlue : theme.chaliceGray)};
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
position: relative;
|
||||
@ -61,7 +62,7 @@ const ExchangeRateWrapper = styled.div`
|
||||
const ExchangeRate = styled.span`
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
color: ${({ theme }) => theme.chaliceGray};
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
`
|
||||
|
||||
const Flex = styled.div`
|
||||
@ -619,7 +620,7 @@ export default function ExchangePage({ initialCurrency, sending }) {
|
||||
}}
|
||||
clickable
|
||||
alt="swap"
|
||||
src={isValid ? ArrowDownBlue : ArrowDownGrey}
|
||||
active={isValid}
|
||||
/>
|
||||
</DownArrowBackground>
|
||||
</OversizedPanel>
|
||||
@ -643,7 +644,7 @@ export default function ExchangePage({ initialCurrency, sending }) {
|
||||
<>
|
||||
<OversizedPanel>
|
||||
<DownArrowBackground>
|
||||
<DownArrow src={isValid ? ArrowDownBlue : ArrowDownGrey} alt="arrow" />
|
||||
<DownArrow active={isValid} alt="arrow" />
|
||||
</DownArrowBackground>
|
||||
</OversizedPanel>
|
||||
<AddressInputPanel onChange={setRecipient} onError={setRecipientError} />
|
||||
|
@ -4,6 +4,7 @@ import styled from 'styled-components'
|
||||
import { Link } from '../../theme'
|
||||
import Web3Status from '../Web3Status'
|
||||
import { darken } from 'polished'
|
||||
import { useDarkModeManager } from '../../contexts/LocalStorage'
|
||||
|
||||
const HeaderElement = styled.div`
|
||||
margin: 1.25rem;
|
||||
@ -15,9 +16,19 @@ const Title = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#image {
|
||||
font-size: 1.5rem;
|
||||
margin-right: 1rem;
|
||||
transform: rotate(0deg);
|
||||
transition: transform 150ms ease-out;
|
||||
|
||||
:hover {
|
||||
transform: rotate(-10deg);
|
||||
}
|
||||
}
|
||||
|
||||
#link {
|
||||
@ -36,11 +47,13 @@ const Title = styled.div`
|
||||
`
|
||||
|
||||
export default function Header() {
|
||||
const [, toggleDarkMode] = useDarkModeManager()
|
||||
|
||||
return (
|
||||
<>
|
||||
<HeaderElement>
|
||||
<Title>
|
||||
<span id="image" role="img" aria-label="Unicorn Emoji">
|
||||
<span onClick={toggleDarkMode} id="image" role="img" aria-label="Unicorn Emoji">
|
||||
🦄
|
||||
</span>
|
||||
|
||||
|
@ -21,8 +21,10 @@ const FilteredDialogContent = ({ minHeight, ...rest }) => <DialogContent {...res
|
||||
const StyledDialogContent = styled(FilteredDialogContent)`
|
||||
&[data-reach-dialog-content] {
|
||||
margin: 0 0 2rem 0;
|
||||
${({ theme }) => theme.mediaWidth.upToMedium`margin: 0;`}
|
||||
padding: 0;
|
||||
border: 1px solid ${({ theme }) => theme.concreteGray};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
${({ theme }) => theme.mediaWidth.upToMedium`margin: 0;`};
|
||||
padding: 0px;
|
||||
width: 50vw;
|
||||
max-width: 650px;
|
||||
${({ theme }) => theme.mediaWidth.upToMedium`width: 65vw;`}
|
||||
@ -51,7 +53,7 @@ const HiddenCloseButton = styled.button`
|
||||
|
||||
export default function Modal({ isOpen, onDismiss, minHeight = false, initialFocusRef, children }) {
|
||||
const transitions = useTransition(isOpen, null, {
|
||||
config: { duration: 125 },
|
||||
config: { duration: 150 },
|
||||
from: { opacity: 0 },
|
||||
enter: { opacity: 1 },
|
||||
leave: { opacity: 0 }
|
||||
|
@ -60,7 +60,7 @@ const Tabs = styled.div`
|
||||
height: 2.5rem;
|
||||
background-color: ${({ theme }) => theme.concreteGray};
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0 0 0 1px ${({ theme }) => darken(0.05, theme.concreteGray)};
|
||||
/* border: 1px solid ${({ theme }) => theme.mercuryGray}; */
|
||||
margin-bottom: 1rem;
|
||||
`
|
||||
|
||||
@ -73,6 +73,7 @@ const StyledNavLink = styled(NavLink).attrs({
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 2.5rem;
|
||||
border: 1px solid ${({ theme }) => transparentize(1, theme.mercuryGray)};
|
||||
flex: 1 0 auto;
|
||||
border-radius: 3rem;
|
||||
outline: none;
|
||||
@ -80,21 +81,24 @@ const StyledNavLink = styled(NavLink).attrs({
|
||||
text-decoration: none;
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
font-size: 1rem;
|
||||
box-sizing: border-box;
|
||||
|
||||
&.${activeClassName} {
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
|
||||
border: 1px solid ${({ theme }) => theme.mercuryGray};
|
||||
box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.royalBlue)};
|
||||
box-sizing: border-box;
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.royalBlue};
|
||||
:hover {
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => darken(0.1, theme.mercuryGray)};
|
||||
border: 1px solid ${({ theme }) => darken(0.1, theme.mercuryGray)};
|
||||
background-color: ${({ theme }) => darken(0.01, theme.inputBackground)};
|
||||
}
|
||||
}
|
||||
|
||||
:hover,
|
||||
:focus {
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => darken(0.1, theme.royalBlue)};
|
||||
}
|
||||
`
|
||||
|
@ -86,12 +86,12 @@ const Popup = styled(Flex)`
|
||||
align-items: center;
|
||||
padding: 0.6rem 1rem;
|
||||
line-height: 150%;
|
||||
background: ${({ theme }) => theme.charcoalBlack};
|
||||
background: ${({ theme }) => theme.inputBackground};
|
||||
border-radius: 8px;
|
||||
|
||||
animation: ${fadeIn} 0.15s linear;
|
||||
|
||||
color: white;
|
||||
color: ${({ theme }) => theme.textColor};
|
||||
font-style: italic;
|
||||
|
||||
${({ theme }) => theme.mediaWidth.upToSmall`
|
||||
@ -100,6 +100,7 @@ const Popup = styled(Flex)`
|
||||
`
|
||||
|
||||
const FancyButton = styled.button`
|
||||
color: ${({ theme }) => theme.textColor};
|
||||
align-items: center;
|
||||
min-width: 55px;
|
||||
height: 2rem;
|
||||
@ -107,7 +108,7 @@ const FancyButton = styled.button`
|
||||
font-size: 12px;
|
||||
border: 1px solid ${({ theme }) => theme.mercuryGray};
|
||||
outline: none;
|
||||
background: ${({ theme }) => theme.white};
|
||||
background: ${({ theme }) => theme.inputBackground};
|
||||
|
||||
:hover {
|
||||
cursor: inherit;
|
||||
@ -115,7 +116,6 @@ const FancyButton = styled.button`
|
||||
}
|
||||
:focus {
|
||||
border: 1px solid ${({ theme }) => theme.royalBlue};
|
||||
/* box-shadow: 0 0 1px 1px #5CA2FF; */
|
||||
}
|
||||
`
|
||||
|
||||
@ -164,8 +164,9 @@ const OptionLarge = styled(Option)`
|
||||
`
|
||||
|
||||
const Input = styled.input`
|
||||
background: ${({ theme }) => theme.white};
|
||||
background: ${({ theme }) => theme.inputBackground};
|
||||
flex-grow: 1;
|
||||
font-size: 12px;
|
||||
|
||||
outline: none;
|
||||
box-sizing: border-box;
|
||||
@ -191,6 +192,7 @@ const Input = styled.input`
|
||||
placeholder !== 'Custom' &&
|
||||
css`
|
||||
text-align: right;
|
||||
color: ${({ theme }) => theme.textColor};
|
||||
`}
|
||||
|
||||
${({ color }) =>
|
||||
@ -479,7 +481,7 @@ export default function TransactionDetails(props) {
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{activeIndex === 4 && warningType.toString() === 'none' && 'Custom slippage value entered'}
|
||||
{activeIndex === 4 && warningType.toString() === 'none' && 'Custom slippage value'}
|
||||
{warningType === WARNING_TYPE.emptyInput && 'Enter a slippage percentage'}
|
||||
{warningType === WARNING_TYPE.invalidEntryBound && 'Please select a value no greater than 50%'}
|
||||
{warningType === WARNING_TYPE.riskyEntryHigh && 'Your transaction may be frontrun'}
|
||||
@ -617,7 +619,6 @@ export default function TransactionDetails(props) {
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>
|
||||
.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('priceChange')} <ValueWrapper>{b(`${props.percentSlippageFormatted}%`)}</ValueWrapper>.
|
||||
@ -638,7 +639,7 @@ export default function TransactionDetails(props) {
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>{' '}
|
||||
{t('to')} {b(props.recipientAddress)}.
|
||||
{t('to')} {b(props.recipientAddress)}
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('itWillCost')}{' '}
|
||||
@ -669,7 +670,6 @@ export default function TransactionDetails(props) {
|
||||
)} ${props.outputSymbol}`
|
||||
)}
|
||||
</ValueWrapper>
|
||||
.
|
||||
</div>
|
||||
<LastSummaryText>
|
||||
{t('itWillCost')}{' '}
|
||||
|
@ -32,8 +32,8 @@ const Web3StatusGeneric = styled.button`
|
||||
`
|
||||
const Web3StatusError = styled(Web3StatusGeneric)`
|
||||
background-color: ${({ theme }) => theme.salmonRed};
|
||||
color: ${({ theme }) => theme.white};
|
||||
border: 1px solid ${({ theme }) => theme.salmonRed};
|
||||
color: ${({ theme }) => theme.white};
|
||||
font-weight: 500;
|
||||
:hover,
|
||||
:focus {
|
||||
@ -43,9 +43,10 @@ const Web3StatusError = styled(Web3StatusGeneric)`
|
||||
|
||||
const Web3StatusConnect = styled(Web3StatusGeneric)`
|
||||
background-color: ${({ theme }) => theme.royalBlue};
|
||||
color: ${({ theme }) => theme.white};
|
||||
border: 1px solid ${({ theme }) => theme.royalBlue};
|
||||
color: ${({ theme }) => theme.white};
|
||||
font-weight: 500;
|
||||
|
||||
:hover,
|
||||
:focus {
|
||||
background-color: ${({ theme }) => darken(0.1, theme.royalBlue)};
|
||||
@ -53,9 +54,9 @@ const Web3StatusConnect = styled(Web3StatusGeneric)`
|
||||
`
|
||||
|
||||
const Web3StatusConnected = styled(Web3StatusGeneric)`
|
||||
background-color: ${({ pending, theme }) => (pending ? theme.zumthorBlue : theme.white)};
|
||||
color: ${({ pending, theme }) => (pending ? theme.royalBlue : theme.doveGray)};
|
||||
background-color: ${({ pending, theme }) => (pending ? theme.zumthorBlue : theme.inputBackground)};
|
||||
border: 1px solid ${({ pending, theme }) => (pending ? theme.royalBlue : theme.mercuryGray)};
|
||||
color: ${({ pending, theme }) => (pending ? theme.royalBlue : theme.doveGray)};
|
||||
font-weight: 400;
|
||||
:hover {
|
||||
background-color: ${({ pending, theme }) =>
|
||||
@ -72,7 +73,6 @@ const Text = styled.p`
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
|
||||
margin: 0 0.5rem 0 0.25rem;
|
||||
font-size: 0.83rem;
|
||||
`
|
||||
|
@ -7,7 +7,8 @@ const CURRENT_VERSION = 0
|
||||
const LAST_SAVED = 'LAST_SAVED'
|
||||
|
||||
const BETA_MESSAGE_DISMISSED = 'BETA_MESSAGE_DISMISSED'
|
||||
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED]
|
||||
const DARK_MODE = 'DARK_MODE'
|
||||
const UPDATABLE_KEYS = [BETA_MESSAGE_DISMISSED, DARK_MODE]
|
||||
|
||||
const UPDATE_KEY = 'UPDATE_KEY'
|
||||
|
||||
@ -39,7 +40,8 @@ function reducer(state, { type, payload }) {
|
||||
function init() {
|
||||
const defaultLocalStorage = {
|
||||
[VERSION]: CURRENT_VERSION,
|
||||
[BETA_MESSAGE_DISMISSED]: false
|
||||
[BETA_MESSAGE_DISMISSED]: false,
|
||||
[DARK_MODE]: false
|
||||
}
|
||||
|
||||
try {
|
||||
@ -48,7 +50,7 @@ function init() {
|
||||
// this is where we could run migration logic
|
||||
return defaultLocalStorage
|
||||
} else {
|
||||
return parsed
|
||||
return { ...defaultLocalStorage, ...parsed }
|
||||
}
|
||||
} catch {
|
||||
return defaultLocalStorage
|
||||
@ -88,3 +90,15 @@ export function useBetaMessageManager() {
|
||||
|
||||
return [!state[BETA_MESSAGE_DISMISSED], dismissBetaMessage]
|
||||
}
|
||||
|
||||
export function useDarkModeManager() {
|
||||
const [state, { updateKey }] = useLocalStorageContext()
|
||||
|
||||
const isDarkMode = state[DARK_MODE]
|
||||
|
||||
const toggleDarkMode = useCallback(() => {
|
||||
updateKey(DARK_MODE, !isDarkMode)
|
||||
}, [updateKey, isDarkMode])
|
||||
|
||||
return [state[DARK_MODE], toggleDarkMode]
|
||||
}
|
||||
|
20
src/index.js
20
src/index.js
@ -55,16 +55,16 @@ function Updaters() {
|
||||
}
|
||||
|
||||
ReactDOM.render(
|
||||
<ThemeProvider>
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<Web3Provider connectors={connectors} libraryName="ethers.js">
|
||||
<ContextProviders>
|
||||
<Updaters />
|
||||
<Web3Provider connectors={connectors} libraryName="ethers.js">
|
||||
<ContextProviders>
|
||||
<Updaters />
|
||||
<ThemeProvider>
|
||||
<>
|
||||
<GlobalStyle />
|
||||
<App />
|
||||
</ContextProviders>
|
||||
</Web3Provider>
|
||||
</>
|
||||
</ThemeProvider>,
|
||||
</>
|
||||
</ThemeProvider>
|
||||
</ContextProviders>
|
||||
</Web3Provider>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
|
@ -9,8 +9,8 @@ import { Button } from '../../theme'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import OversizedPanel from '../../components/OversizedPanel'
|
||||
import ContextualInfo from '../../components/ContextualInfo'
|
||||
import PlusBlue from '../../assets/images/plus-blue.svg'
|
||||
import PlusGrey from '../../assets/images/plus-grey.svg'
|
||||
import { ReactComponent as Plus } from '../../assets/images/plus-blue.svg'
|
||||
|
||||
import { useExchangeContract } from '../../hooks'
|
||||
import { amountFormatter, calculateGasMargin } from '../../utils'
|
||||
import { useTransactionAdder } from '../../contexts/Transactions'
|
||||
@ -63,14 +63,6 @@ const DownArrowBackground = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const DownArrow = styled.img`
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
position: relative;
|
||||
padding: 0.875rem;
|
||||
`
|
||||
|
||||
const SummaryPanel = styled.div`
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
padding: 1rem 0;
|
||||
@ -87,7 +79,7 @@ const ExchangeRateWrapper = styled.div`
|
||||
const ExchangeRate = styled.span`
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
color: ${({ theme }) => theme.chaliceGray};
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
`
|
||||
|
||||
const Flex = styled.div`
|
||||
@ -100,6 +92,17 @@ const Flex = styled.div`
|
||||
}
|
||||
`
|
||||
|
||||
const WrappedPlus = ({ isError, highSlippageWarning, ...rest }) => <Plus {...rest} />
|
||||
const ColoredWrappedPlus = styled(WrappedPlus)`
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
position: relative;
|
||||
padding: 0.875rem;
|
||||
path {
|
||||
stroke: ${({ active, theme }) => (active ? theme.royalBlue : theme.chaliceGray)};
|
||||
}
|
||||
`
|
||||
|
||||
function calculateSlippageBounds(value) {
|
||||
if (value) {
|
||||
const offset = value.mul(ALLOWED_SLIPPAGE).div(ethers.utils.bigNumberify(10000))
|
||||
@ -558,7 +561,7 @@ export default function AddLiquidity() {
|
||||
/>
|
||||
<OversizedPanel>
|
||||
<DownArrowBackground>
|
||||
<DownArrow src={isActive ? PlusBlue : PlusGrey} alt="plus" />
|
||||
<ColoredWrappedPlus active={isActive} alt="plus" />
|
||||
</DownArrowBackground>
|
||||
</OversizedPanel>
|
||||
<CurrencyInputPanel
|
||||
|
@ -29,7 +29,7 @@ const ExchangeRateWrapper = styled.div`
|
||||
const ExchangeRate = styled.span`
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
color: ${({ theme }) => theme.chaliceGray};
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
`
|
||||
|
||||
const CreateExchangeWrapper = styled.div`
|
||||
|
@ -4,10 +4,13 @@ import { useTranslation } from 'react-i18next'
|
||||
import styled from 'styled-components'
|
||||
|
||||
import OversizedPanel from '../../components/OversizedPanel'
|
||||
import Dropdown from '../../assets/images/dropdown-blue.svg'
|
||||
import { ReactComponent as Dropdown } from '../../assets/images/dropdown-blue.svg'
|
||||
|
||||
import Modal from '../../components/Modal'
|
||||
import { useBodyKeyDown } from '../../hooks'
|
||||
|
||||
import { lighten } from 'polished'
|
||||
|
||||
const poolTabOrder = [
|
||||
{
|
||||
path: '/add-liquidity',
|
||||
@ -29,13 +32,16 @@ const poolTabOrder = [
|
||||
const LiquidityContainer = styled.div`
|
||||
${({ theme }) => theme.flexRowNoWrap};
|
||||
align-items: center;
|
||||
font-size: 0.75rem;
|
||||
padding: 0.625rem 1rem;
|
||||
font-size: 0.75rem;
|
||||
padding: 1rem 1rem;
|
||||
font-size: 1rem;
|
||||
color: ${({ theme }) => theme.royalBlue};
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
|
||||
:hover {
|
||||
color: ${({ theme }) => lighten(0.1, theme.royalBlue)};
|
||||
}
|
||||
|
||||
img {
|
||||
height: 0.75rem;
|
||||
width: 0.75rem;
|
||||
@ -62,21 +68,28 @@ const StyledNavLink = styled(NavLink).attrs({
|
||||
font-size: 1rem;
|
||||
|
||||
&.${activeClassName} {
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0 0 1px 1px ${({ theme }) => theme.mercuryGray};
|
||||
border: 1px solid ${({ theme }) => theme.mercuryGray};
|
||||
font-weight: 500;
|
||||
color: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
`
|
||||
|
||||
const PoolModal = styled.div`
|
||||
background-color: ${({ theme }) => theme.white};
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 2rem 0 2rem 0;
|
||||
`
|
||||
|
||||
const WrappedDropdown = ({ isError, highSlippageWarning, ...rest }) => <Dropdown {...rest} />
|
||||
const ColoredDropdown = styled(WrappedDropdown)`
|
||||
path {
|
||||
stroke: ${({ theme }) => theme.royalBlue};
|
||||
}
|
||||
`
|
||||
|
||||
function ModeSelector({ location: { pathname }, history }) {
|
||||
const { t } = useTranslation()
|
||||
|
||||
@ -109,7 +122,7 @@ function ModeSelector({ location: { pathname }, history }) {
|
||||
}}
|
||||
>
|
||||
<LiquidityLabel>{t(activeTabKey)}</LiquidityLabel>
|
||||
<img src={Dropdown} alt="dropdown" />
|
||||
<ColoredDropdown alt="arrow down" />
|
||||
</LiquidityContainer>
|
||||
<Modal
|
||||
isOpen={modalIsOpen}
|
||||
|
@ -9,8 +9,8 @@ import { Button } from '../../theme'
|
||||
import CurrencyInputPanel from '../../components/CurrencyInputPanel'
|
||||
import ContextualInfo from '../../components/ContextualInfo'
|
||||
import OversizedPanel from '../../components/OversizedPanel'
|
||||
import ArrowDownBlue from '../../assets/images/arrow-down-blue.svg'
|
||||
import ArrowDownGrey from '../../assets/images/arrow-down-grey.svg'
|
||||
import ArrowDown from '../../assets/svg/SVGArrowDown'
|
||||
|
||||
import { useExchangeContract } from '../../hooks'
|
||||
import { useTransactionAdder } from '../../contexts/Transactions'
|
||||
import { useTokenDetails } from '../../contexts/Tokens'
|
||||
@ -36,7 +36,9 @@ const DownArrowBackground = styled.div`
|
||||
align-items: center;
|
||||
`
|
||||
|
||||
const DownArrow = styled.img`
|
||||
const DownArrow = styled(ArrowDown)`
|
||||
${({ theme }) => theme.flexRowNoWrap}
|
||||
color: ${({ theme, active }) => (active ? theme.royalBlue : theme.doveGray)};
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
position: relative;
|
||||
@ -80,7 +82,7 @@ const ExchangeRateWrapper = styled.div`
|
||||
const ExchangeRate = styled.span`
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
color: ${({ theme }) => theme.chaliceGray};
|
||||
color: ${({ theme }) => theme.doveGray};
|
||||
`
|
||||
|
||||
const Flex = styled.div`
|
||||
@ -347,7 +349,7 @@ export default function RemoveLiquidity() {
|
||||
/>
|
||||
<OversizedPanel>
|
||||
<DownArrowBackground>
|
||||
<DownArrow src={isActive ? ArrowDownBlue : ArrowDownGrey} alt="arrow" />
|
||||
<DownArrow active={isActive} alt="arrow" />
|
||||
</DownArrowBackground>
|
||||
</OversizedPanel>
|
||||
<CurrencyInputPanel
|
||||
|
@ -12,8 +12,8 @@ export const Button = styled.button.attrs(({ warning, theme }) => ({
|
||||
border: none;
|
||||
outline: none;
|
||||
background-color: ${({ backgroundColor }) => backgroundColor};
|
||||
transition: background-color 150ms ease-out;
|
||||
color: ${({ theme }) => theme.white};
|
||||
transition: background-color 125ms ease-in-out;
|
||||
width: 100%;
|
||||
|
||||
:hover,
|
||||
@ -26,7 +26,8 @@ export const Button = styled.button.attrs(({ warning, theme }) => ({
|
||||
}
|
||||
|
||||
:disabled {
|
||||
background-color: ${({ theme }) => theme.mercuryGray};
|
||||
background-color: ${({ theme }) => theme.concreteGray};
|
||||
color: ${({ theme }) => theme.silverGray};
|
||||
cursor: auto;
|
||||
}
|
||||
`
|
||||
@ -50,12 +51,13 @@ export const Link = styled.a.attrs({
|
||||
`
|
||||
|
||||
export const BorderlessInput = styled.input`
|
||||
color: ${({ theme }) => theme.mineshaftGray};
|
||||
color: ${({ theme }) => theme.textColor};
|
||||
font-size: 1rem;
|
||||
outline: none;
|
||||
border: none;
|
||||
flex: 1 1 auto;
|
||||
width: 0;
|
||||
background-color: ${({ theme }) => theme.inputBackground};
|
||||
|
||||
[type='number'] {
|
||||
-moz-appearance: textfield;
|
||||
@ -67,7 +69,7 @@ export const BorderlessInput = styled.input`
|
||||
}
|
||||
|
||||
::placeholder {
|
||||
color: ${({ theme }) => theme.mercuryGray};
|
||||
color: ${({ theme }) => theme.placeholderGray};
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import React from 'react'
|
||||
import { ThemeProvider as StyledComponentsThemeProvider, createGlobalStyle, css } from 'styled-components'
|
||||
import { useDarkModeManager } from '../contexts/LocalStorage'
|
||||
|
||||
export * from './components'
|
||||
|
||||
@ -28,23 +29,34 @@ const flexRowNoWrap = css`
|
||||
flex-flow: row nowrap;
|
||||
`
|
||||
|
||||
const theme = {
|
||||
white: '#FFFFFF',
|
||||
black: '#000000',
|
||||
const white = '#FFFFFF'
|
||||
const black = '#000000'
|
||||
|
||||
const theme = darkMode => ({
|
||||
white,
|
||||
black,
|
||||
textColor: darkMode ? white : '#010101',
|
||||
|
||||
// for setting css on <html>
|
||||
backgroundColor: darkMode ? '#333639' : white,
|
||||
|
||||
inputBackground: darkMode ? '#202124' : white,
|
||||
placeholderGray: darkMode ? '#5F5F5F' : '#E1E1E1',
|
||||
|
||||
// grays
|
||||
concreteGray: '#FAFAFA',
|
||||
mercuryGray: '#E1E1E1',
|
||||
silverGray: '#C4C4C4',
|
||||
chaliceGray: '#AEAEAE',
|
||||
doveGray: '#737373',
|
||||
mineshaftGray: '#2B2B2B',
|
||||
buttonOutlineGrey: '#f2f2f2',
|
||||
concreteGray: darkMode ? '#292C2F' : '#FAFAFA',
|
||||
mercuryGray: darkMode ? '#333333' : '#E1E1E1',
|
||||
silverGray: darkMode ? '#737373' : '#C4C4C4',
|
||||
chaliceGray: darkMode ? '#7B7B7B' : '#AEAEAE',
|
||||
doveGray: darkMode ? '#C4C4C4' : '#737373',
|
||||
mineshaftGray: darkMode ? '#E1E1E1' : '#2B2B2B',
|
||||
buttonOutlineGrey: darkMode ? '#FAFAFA' : '#F2F2F2',
|
||||
//blacks
|
||||
charcoalBlack: '#404040',
|
||||
charcoalBlack: darkMode ? '#F2F2F2' : '#404040',
|
||||
// blues
|
||||
zumthorBlue: '#EBF4FF',
|
||||
malibuBlue: '#5CA2FF',
|
||||
royalBlue: '#2F80ED',
|
||||
zumthorBlue: darkMode ? '#212529' : '#EBF4FF',
|
||||
malibuBlue: darkMode ? '#E67AEF' : '#5CA2FF',
|
||||
royalBlue: darkMode ? '#DC6BE5' : '#2F80ED',
|
||||
// purples
|
||||
wisteriaPurple: '#DC6BE5',
|
||||
// reds
|
||||
@ -62,10 +74,12 @@ const theme = {
|
||||
// css snippets
|
||||
flexColumnNoWrap,
|
||||
flexRowNoWrap
|
||||
}
|
||||
})
|
||||
|
||||
export default function ThemeProvider({ children }) {
|
||||
return <StyledComponentsThemeProvider theme={theme}>{children}</StyledComponentsThemeProvider>
|
||||
const [darkMode] = useDarkModeManager()
|
||||
|
||||
return <StyledComponentsThemeProvider theme={theme(darkMode)}>{children}</StyledComponentsThemeProvider>
|
||||
}
|
||||
|
||||
export const GlobalStyle = createGlobalStyle`
|
||||
@ -79,20 +93,16 @@ export const GlobalStyle = createGlobalStyle`
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 16px;
|
||||
font-variant: none;
|
||||
color: ${({ theme }) => theme.textColor};
|
||||
background-color: ${({ theme }) => theme.backgroundColor};
|
||||
transition: color 150ms ease-out, background-color 150ms ease-out;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#root {
|
||||
${({ theme }) => theme.flexColumnNoWrap}
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
}
|
||||
`
|
||||
|
Loading…
Reference in New Issue
Block a user