feat: wallet hover styling and moving wallet to correct navbar (#4444)

* updating wallet to have correct hover highlighting and have correct scrolling

Co-authored-by: Alex Ball <alexball@UNISWAP-MAC-038.local>
This commit is contained in:
aballerr 2022-08-23 11:00:36 -04:00 committed by GitHub
parent 9873491db1
commit 68db8b3e23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 116 additions and 69 deletions

@ -25,6 +25,11 @@ const Grid = styled.a`
text-decoration: none; text-decoration: none;
border-bottom: ${({ theme }) => `1px solid ${theme.backgroundOutline}`}; border-bottom: ${({ theme }) => `1px solid ${theme.backgroundOutline}`};
padding: 12px; padding: 12px;
&:hover {
background-color: ${({ theme }) => theme.backgroundModule};
transition: 250ms background-color ease;
}
` `
const TextContainer = styled.span` const TextContainer = styled.span`

@ -5,7 +5,6 @@ import { RedesignVariant, useRedesignFlag } from 'featureFlags/flags/redesign'
import { TokensVariant, useTokensFlag } from 'featureFlags/flags/tokens' import { TokensVariant, useTokensFlag } from 'featureFlags/flags/tokens'
import { TokenSafetyVariant, useTokenSafetyFlag } from 'featureFlags/flags/tokenSafety' import { TokenSafetyVariant, useTokenSafetyFlag } from 'featureFlags/flags/tokenSafety'
import { TokensNetworkFilterVariant, useTokensNetworkFilterFlag } from 'featureFlags/flags/tokensNetworkFilter' import { TokensNetworkFilterVariant, useTokensNetworkFilterFlag } from 'featureFlags/flags/tokensNetworkFilter'
import { useWalletFlag, WalletVariant } from 'featureFlags/flags/wallet'
import { useAtomValue } from 'jotai/utils' import { useAtomValue } from 'jotai/utils'
import { ReactNode, useState } from 'react' import { ReactNode, useState } from 'react'
import { X } from 'react-feather' import { X } from 'react-feather'
@ -203,12 +202,6 @@ export default function FeatureFlagModal() {
featureFlag={FeatureFlag.tokenSafety} featureFlag={FeatureFlag.tokenSafety}
label="Token Safety" label="Token Safety"
/> />
<FeatureFlagOption
variants={Object.values(WalletVariant)}
value={useWalletFlag()}
featureFlag={FeatureFlag.wallet}
label="Wallet Flag"
/>
<SaveButton onClick={() => window.location.reload()}>Save Settings</SaveButton> <SaveButton onClick={() => window.location.reload()}>Save Settings</SaveButton>
</Modal> </Modal>
) )

@ -1,11 +1,9 @@
import { Trans } from '@lingui/macro' import { Trans } from '@lingui/macro'
import useScrollPosition from '@react-hook/window-scroll' import useScrollPosition from '@react-hook/window-scroll'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import WalletDropdown from 'components/WalletDropdown'
import { getChainInfoOrDefault } from 'constants/chainInfo' import { getChainInfoOrDefault } from 'constants/chainInfo'
import { SupportedChainId } from 'constants/chains' import { SupportedChainId } from 'constants/chains'
import { TokensVariant, useTokensFlag } from 'featureFlags/flags/tokens' import { TokensVariant, useTokensFlag } from 'featureFlags/flags/tokens'
import { useWalletFlag, WalletVariant } from 'featureFlags/flags/wallet'
import { darken } from 'polished' import { darken } from 'polished'
import { NavLink, useLocation } from 'react-router-dom' import { NavLink, useLocation } from 'react-router-dom'
import { Text } from 'rebass' import { Text } from 'rebass'
@ -219,12 +217,6 @@ const StyledNavLink = styled(NavLink)`
} }
` `
const WalletDropdownWrapper = styled.div`
position: absolute;
top: 75px;
right: 20px;
`
const StyledExternalLink = styled(ExternalLink)` const StyledExternalLink = styled(ExternalLink)`
${({ theme }) => theme.flexRowNoWrap} ${({ theme }) => theme.flexRowNoWrap}
align-items: left; align-items: left;
@ -252,7 +244,6 @@ const StyledExternalLink = styled(ExternalLink)`
` `
export default function Header() { export default function Header() {
const walletFlag = useWalletFlag()
const tokensFlag = useTokensFlag() const tokensFlag = useTokensFlag()
const { account, chainId } = useWeb3React() const { account, chainId } = useWeb3React()
@ -355,11 +346,6 @@ export default function Header() {
) : null} ) : null}
<Web3Status /> <Web3Status />
</AccountElement> </AccountElement>
{walletFlag === WalletVariant.Enabled && (
<WalletDropdownWrapper>
<WalletDropdown />
</WalletDropdownWrapper>
)}
</HeaderElement> </HeaderElement>
<HeaderElement> <HeaderElement>
<Menu /> <Menu />

@ -81,6 +81,10 @@ const HeaderWrapper = styled.div`
justify-content: space-between; justify-content: space-between;
` `
const AuthenticatedHeaderWrapper = styled.div`
padding: 0 16px;
`
const AuthenticatedHeader = () => { const AuthenticatedHeader = () => {
const { account, chainId, connector } = useWeb3React() const { account, chainId, connector } = useWeb3React()
const [isCopied, setCopied] = useCopyClipboard() const [isCopied, setCopied] = useCopyClipboard()
@ -115,7 +119,7 @@ const AuthenticatedHeader = () => {
}, [balanceString, nativeCurrencyPrice]) }, [balanceString, nativeCurrencyPrice])
return ( return (
<> <AuthenticatedHeaderWrapper>
<HeaderWrapper> <HeaderWrapper>
<StatusWrapper> <StatusWrapper>
<FlexContainer> <FlexContainer>
@ -144,7 +148,7 @@ const AuthenticatedHeader = () => {
</UNIbutton> </UNIbutton>
)} )}
</Column> </Column>
</> </AuthenticatedHeaderWrapper>
) )
} }

@ -18,6 +18,8 @@ const ConnectButton = styled(ButtonPrimary)`
width: 288px; width: 288px;
font-weight: 600; font-weight: 600;
font-size: 16px; font-size: 16px;
margin-left: auto;
margin-right: auto;
` `
const Divider = styled.div` const Divider = styled.div`
@ -35,16 +37,16 @@ const ToggleMenuItem = styled.button`
flex: 1; flex: 1;
flex-direction: row; flex-direction: row;
align-items: center; align-items: center;
padding: 8px 0px;
justify-content: space-between; justify-content: space-between;
font-size: 14px; font-size: 14px;
font-weight: 400; font-weight: 400;
width: 100%; width: 100%;
margin-bottom: 8px; padding: 12px 16px;
color: ${({ theme }) => theme.textSecondary}; color: ${({ theme }) => theme.textSecondary};
:hover { :hover {
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
transition: 250ms color ease; background-color: ${({ theme }) => theme.backgroundModule};
transition: 250ms all ease;
} }
` `
@ -69,7 +71,6 @@ const IconWrap = styled.span`
` `
const DefaultMenuWrap = styled.div` const DefaultMenuWrap = styled.div`
padding: 0 16px;
width: 100%; width: 100%;
height: 100%; height: 100%;
` `

@ -24,7 +24,7 @@ const IconStyles = css`
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
:hover { :hover {
background-color: ${({ theme }) => theme.hoverState}; background-color: ${({ theme }) => theme.hoverState};
transition: background-color 200ms linear; transition: 250ms background-color ease;
${IconHoverText} { ${IconHoverText} {
opacity: 1; opacity: 1;

@ -29,6 +29,8 @@ const InternalLinkMenuItem = styled(InternalMenuItem)<{ isActive: boolean }>`
color: ${({ theme }) => theme.textPrimary}; color: ${({ theme }) => theme.textPrimary};
:hover { :hover {
cursor: pointer; cursor: pointer;
background-color: ${({ isActive, theme }) => !isActive && theme.backgroundModule};
transition: 250ms background-color ease;
} }
` `

@ -1,17 +1,6 @@
import { ChevronLeft } from 'react-feather' import { ChevronLeft } from 'react-feather'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
const BackSection = styled.div`
position: relative;
display: flex;
padding: 0 16px;
color: ${({ theme }) => theme.textSecondary};
cursor: default;
:hover {
text-decoration: none;
}
`
const Menu = styled.div` const Menu = styled.div`
width: 100%; width: 100%;
height: 100%; height: 100%;
@ -29,12 +18,16 @@ const Header = styled.span`
const ClearAll = styled.div` const ClearAll = styled.div`
display: inline-block; display: inline-block;
cursor: pointer; cursor: pointer;
margin-left: auto;
color: ${({ theme }) => theme.accentAction}; color: ${({ theme }) => theme.accentAction};
font-weight: 600; font-weight: 600;
font-size: 14px; font-size: 14px;
margin-top: auto; margin-top: auto;
margin-bottom: auto; margin-bottom: auto;
:hover {
opacity: 0.6;
transition: 250ms opacity ease;
}
` `
const StyledChevron = styled(ChevronLeft)` const StyledChevron = styled(ChevronLeft)`
@ -46,6 +39,28 @@ const StyledChevron = styled(ChevronLeft)`
} }
` `
const BackSection = styled.div`
position: absolute;
background-color: ${({ theme }) => theme.backgroundSurface};
width: 100%;
padding: 0 16px 16px 16px;
color: ${({ theme }) => theme.textSecondary};
cursor: default;
display: flex;
justify-content: space-between;
`
const BackSectionContainer = styled.div`
display: flex;
justify-content: space-between;
position: relative;
width: 100%;
`
const ChildrenContainer = styled.div`
margin-top: 40px;
`
export const SlideOutMenu = ({ export const SlideOutMenu = ({
children, children,
onClose, onClose,
@ -59,10 +74,13 @@ export const SlideOutMenu = ({
}) => ( }) => (
<Menu> <Menu>
<BackSection> <BackSection>
<StyledChevron onClick={onClose} size={24} /> <BackSectionContainer>
<Header>{title}</Header> <StyledChevron onClick={onClose} size={24} />
{onClear && <ClearAll onClick={onClear}>Clear All</ClearAll>} <Header>{title}</Header>
{onClear && <ClearAll onClick={onClear}>Clear All</ClearAll>}
</BackSectionContainer>
</BackSection> </BackSection>
{children}
<ChildrenContainer>{children}</ChildrenContainer>
</Menu> </Menu>
) )

@ -1,6 +1,8 @@
import { useState } from 'react' import { useState } from 'react'
import styled from 'styled-components/macro' import styled from 'styled-components/macro'
import { useModalIsOpen } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import DefaultMenu from './DefaultMenu' import DefaultMenu from './DefaultMenu'
import LanguageMenu from './LanguageMenu' import LanguageMenu from './LanguageMenu'
import { TransactionHistoryMenu } from './TransactionMenu' import { TransactionHistoryMenu } from './TransactionMenu'
@ -9,7 +11,6 @@ const WalletWrapper = styled.div`
border-radius: 12px; border-radius: 12px;
width: 320px; width: 320px;
max-height: 376px; max-height: 376px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
font-size: 16px; font-size: 16px;
@ -25,15 +26,37 @@ export enum MenuState {
TRANSACTIONS = 'TRANSACTIONS', TRANSACTIONS = 'TRANSACTIONS',
} }
const WalletDropdownWrapper = styled.div`
position: absolute;
@media only screen and (min-width: 1280px) {
top: 65px;
right: 20px;
}
@media only screen and (max-width: 1280px) {
left: 50%;
bottom: 45px;
transform: translateX(-50%);
}
`
const WalletDropdown = () => { const WalletDropdown = () => {
const [menu, setMenu] = useState<MenuState>(MenuState.DEFAULT) const [menu, setMenu] = useState<MenuState>(MenuState.DEFAULT)
const walletDropdownOpen = useModalIsOpen(ApplicationModal.WALLET_DROPDOWN)
return ( return (
<WalletWrapper> <>
{menu === MenuState.TRANSACTIONS && <TransactionHistoryMenu onClose={() => setMenu(MenuState.DEFAULT)} />} {walletDropdownOpen && (
{menu === MenuState.LANGUAGE && <LanguageMenu onClose={() => setMenu(MenuState.DEFAULT)} />} <WalletDropdownWrapper>
{menu === MenuState.DEFAULT && <DefaultMenu setMenu={setMenu} />} <WalletWrapper>
</WalletWrapper> {menu === MenuState.TRANSACTIONS && <TransactionHistoryMenu onClose={() => setMenu(MenuState.DEFAULT)} />}
{menu === MenuState.LANGUAGE && <LanguageMenu onClose={() => setMenu(MenuState.DEFAULT)} />}
{menu === MenuState.DEFAULT && <DefaultMenu setMenu={setMenu} />}
</WalletWrapper>
</WalletDropdownWrapper>
)}
</>
) )
} }

@ -3,17 +3,22 @@ import { t, Trans } from '@lingui/macro'
import { useWeb3React } from '@web3-react/core' import { useWeb3React } from '@web3-react/core'
import { ElementName, Event, EventName } from 'components/AmplitudeAnalytics/constants' import { ElementName, Event, EventName } from 'components/AmplitudeAnalytics/constants'
import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent' import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent'
import WalletDropdown from 'components/WalletDropdown'
import { getConnection } from 'connection/utils' import { getConnection } from 'connection/utils'
import { NavBarVariant, useNavBarFlag } from 'featureFlags/flags/navBar'
import { getIsValidSwapQuote } from 'pages/Swap' import { getIsValidSwapQuote } from 'pages/Swap'
import { darken } from 'polished' import { darken } from 'polished'
import { useMemo } from 'react' import { useMemo, useRef } from 'react'
import { AlertTriangle } from 'react-feather' import { AlertTriangle } from 'react-feather'
import { useAppSelector } from 'state/hooks' import { useAppSelector } from 'state/hooks'
import { useDerivedSwapInfo } from 'state/swap/hooks' import { useDerivedSwapInfo } from 'state/swap/hooks'
import styled, { css } from 'styled-components/macro' import styled, { css } from 'styled-components/macro'
import { useOnClickOutside } from '../../hooks/useOnClickOutside'
import { useHasSocks } from '../../hooks/useSocksBalance' import { useHasSocks } from '../../hooks/useSocksBalance'
import { useToggleWalletModal } from '../../state/application/hooks' import { useModalIsOpen, useToggleWalletDropdown, useToggleWalletModal } from '../../state/application/hooks'
import { useCloseModal } from '../../state/application/hooks'
import { ApplicationModal } from '../../state/application/reducer'
import { isTransactionRecent, useAllTransactions } from '../../state/transactions/hooks' import { isTransactionRecent, useAllTransactions } from '../../state/transactions/hooks'
import { TransactionDetails } from '../../state/transactions/types' import { TransactionDetails } from '../../state/transactions/types'
import { shortenAddress } from '../../utils' import { shortenAddress } from '../../utils'
@ -133,6 +138,9 @@ function Web3StatusInner() {
inputError: swapInputError, inputError: swapInputError,
} = useDerivedSwapInfo() } = useDerivedSwapInfo()
const validSwapQuote = getIsValidSwapQuote(trade, tradeState, swapInputError) const validSwapQuote = getIsValidSwapQuote(trade, tradeState, swapInputError)
const navbarFlag = useNavBarFlag()
const toggleWalletDropdown = useToggleWalletDropdown()
const toggleWalletModal = useToggleWalletModal()
const error = useAppSelector((state) => state.connection.errorByConnectionType[getConnection(connector).type]) const error = useAppSelector((state) => state.connection.errorByConnectionType[getConnection(connector).type])
@ -147,13 +155,13 @@ function Web3StatusInner() {
const hasPendingTransactions = !!pending.length const hasPendingTransactions = !!pending.length
const hasSocks = useHasSocks() const hasSocks = useHasSocks()
const toggleWalletModal = useToggleWalletModal() const toggleWallet = navbarFlag === NavBarVariant.Enabled ? toggleWalletDropdown : toggleWalletModal
if (!chainId) { if (!chainId) {
return null return null
} else if (error) { } else if (error) {
return ( return (
<Web3StatusError onClick={toggleWalletModal}> <Web3StatusError onClick={toggleWallet}>
<NetworkIcon /> <NetworkIcon />
<Text> <Text>
<Trans>Error</Trans> <Trans>Error</Trans>
@ -162,11 +170,7 @@ function Web3StatusInner() {
) )
} else if (account) { } else if (account) {
return ( return (
<Web3StatusConnected <Web3StatusConnected data-testid="web3-status-connected" onClick={toggleWallet} pending={hasPendingTransactions}>
data-testid="web3-status-connected"
onClick={toggleWalletModal}
pending={hasPendingTransactions}
>
{hasPendingTransactions ? ( {hasPendingTransactions ? (
<RowBetween> <RowBetween>
<Text> <Text>
@ -191,7 +195,7 @@ function Web3StatusInner() {
properties={{ received_swap_quote: validSwapQuote }} properties={{ received_swap_quote: validSwapQuote }}
element={ElementName.CONNECT_WALLET_BUTTON} element={ElementName.CONNECT_WALLET_BUTTON}
> >
<Web3StatusConnect onClick={toggleWalletModal} faded={!account}> <Web3StatusConnect onClick={toggleWallet} faded={!account}>
<Text> <Text>
<Trans>Connect Wallet</Trans> <Trans>Connect Wallet</Trans>
</Text> </Text>
@ -201,10 +205,22 @@ function Web3StatusInner() {
} }
} }
const useIsOpen = () => {
const walletDropdownOpen = useModalIsOpen(ApplicationModal.WALLET_DROPDOWN)
const navbarFlag = useNavBarFlag()
return useMemo(() => navbarFlag === NavBarVariant.Enabled && walletDropdownOpen, [navbarFlag, walletDropdownOpen])
}
export default function Web3Status() { export default function Web3Status() {
const { ENSName } = useWeb3React() const { ENSName } = useWeb3React()
const allTransactions = useAllTransactions() const allTransactions = useAllTransactions()
const ref = useRef<HTMLDivElement>(null)
const closeModal = useCloseModal(ApplicationModal.WALLET_DROPDOWN)
const isOpen = useIsOpen()
useOnClickOutside(ref, isOpen ? closeModal : undefined)
const sortedRecentTransactions = useMemo(() => { const sortedRecentTransactions = useMemo(() => {
const txs = Object.values(allTransactions) const txs = Object.values(allTransactions)
@ -215,9 +231,10 @@ export default function Web3Status() {
const confirmed = sortedRecentTransactions.filter((tx) => tx.receipt).map((tx) => tx.hash) const confirmed = sortedRecentTransactions.filter((tx) => tx.receipt).map((tx) => tx.hash)
return ( return (
<> <span ref={ref}>
<Web3StatusInner /> <Web3StatusInner />
<WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} /> <WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} />
</> <WalletDropdown />
</span>
) )
} }

@ -1,7 +0,0 @@
import { BaseVariant, FeatureFlag, useBaseFlag } from '../index'
export function useWalletFlag(): BaseVariant {
return useBaseFlag(FeatureFlag.wallet)
}
export { BaseVariant as WalletVariant }

@ -30,6 +30,10 @@ export function useToggleWalletModal(): () => void {
return useToggleModal(ApplicationModal.WALLET) return useToggleModal(ApplicationModal.WALLET)
} }
export function useToggleWalletDropdown(): () => void {
return useToggleModal(ApplicationModal.WALLET_DROPDOWN)
}
export function useToggleSettingsMenu(): () => void { export function useToggleSettingsMenu(): () => void {
return useToggleModal(ApplicationModal.SETTINGS) return useToggleModal(ApplicationModal.SETTINGS)
} }

@ -26,6 +26,7 @@ export enum ApplicationModal {
SETTINGS, SETTINGS,
VOTE, VOTE,
WALLET, WALLET,
WALLET_DROPDOWN,
QUEUE, QUEUE,
EXECUTE, EXECUTE,
TIME_SELECTOR, TIME_SELECTOR,