Commit fdbe4b8f authored by Charles Bachmeier's avatar Charles Bachmeier Committed by GitHub

feat: mobile network switcher (#4486)

* feat: mobile network switcher

* adjust bottom border radius on mobile
Co-authored-by: default avatarCharlie <charlie@uniswap.org>
parent 33c73f4d
import { style } from '@vanilla-extract/css' import { style } from '@vanilla-extract/css'
import { lightGrayOverlayOnHover } from 'nft/css/common.css' import { lightGrayOverlayOnHover } from 'nft/css/common.css'
import { sprinkles } from '../../nft/css/sprinkles.css' import { breakpoints, sprinkles } from '../../nft/css/sprinkles.css'
export const ChainSwitcher = style([ export const ChainSwitcher = style([
lightGrayOverlayOnHover, lightGrayOverlayOnHover,
...@@ -26,11 +26,16 @@ export const ChainSwitcherRow = style([ ...@@ -26,11 +26,16 @@ export const ChainSwitcherRow = style([
cursor: 'pointer', cursor: 'pointer',
color: 'blackBlue', color: 'blackBlue',
borderRadius: '12', borderRadius: '12',
width: { sm: 'full' },
}), }),
{ {
lineHeight: '24px', lineHeight: '24px',
'@media': {
[`screen and (min-width: ${breakpoints.sm}px)`]: {
width: '204px', width: '204px',
}, },
},
},
]) ])
export const Image = style([ export const Image = style([
......
...@@ -5,10 +5,12 @@ import { useOnClickOutside } from 'hooks/useOnClickOutside' ...@@ -5,10 +5,12 @@ import { useOnClickOutside } from 'hooks/useOnClickOutside'
import useSelectChain from 'hooks/useSelectChain' import useSelectChain from 'hooks/useSelectChain'
import useSyncChainQuery from 'hooks/useSyncChainQuery' import useSyncChainQuery from 'hooks/useSyncChainQuery'
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import { Portal } from 'nft/components/common/Portal'
import { Column, Row } from 'nft/components/Flex' import { Column, Row } from 'nft/components/Flex'
import { CheckMarkIcon, NewChevronDownIcon, NewChevronUpIcon, TokenWarningRedIcon } from 'nft/components/icons' import { CheckMarkIcon, NewChevronDownIcon, NewChevronUpIcon, TokenWarningRedIcon } from 'nft/components/icons'
import { subhead } from 'nft/css/common.css' import { subhead } from 'nft/css/common.css'
import { themeVars, vars } from 'nft/css/sprinkles.css' import { themeVars, vars } from 'nft/css/sprinkles.css'
import { useIsMobile } from 'nft/hooks'
import { ReactNode, useReducer, useRef } from 'react' import { ReactNode, useReducer, useRef } from 'react'
import { isChainAllowed } from 'utils/switchChain' import { isChainAllowed } from 'utils/switchChain'
...@@ -55,12 +57,13 @@ const NETWORK_SELECTOR_CHAINS = [ ...@@ -55,12 +57,13 @@ const NETWORK_SELECTOR_CHAINS = [
] ]
interface ChainSwitcherProps { interface ChainSwitcherProps {
isMobile?: boolean leftAlign?: boolean
} }
export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => { export const ChainSwitcher = ({ leftAlign }: ChainSwitcherProps) => {
const { chainId } = useWeb3React() const { chainId } = useWeb3React()
const [isOpen, toggleOpen] = useReducer((s) => !s, false) const [isOpen, toggleOpen] = useReducer((s) => !s, false)
const isMobile = useIsMobile()
const ref = useRef<HTMLDivElement>(null) const ref = useRef<HTMLDivElement>(null)
useOnClickOutside(ref, isOpen ? toggleOpen : undefined) useOnClickOutside(ref, isOpen ? toggleOpen : undefined)
...@@ -76,6 +79,25 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => { ...@@ -76,6 +79,25 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => {
const isSupported = isChainAllowed(chainId) const isSupported = isChainAllowed(chainId)
const dropdown = (
<NavDropdown top={54} leftAligned={leftAlign} paddingBottom={8} paddingTop={8}>
<Column marginX="8">
{NETWORK_SELECTOR_CHAINS.map((chainId: SupportedChainId) =>
isSupported ? (
<ChainRow
onSelectChain={async (targetChainId: SupportedChainId) => {
await selectChain(targetChainId)
toggleOpen()
}}
targetChain={chainId}
key={chainId}
/>
) : null
)}
</Column>
</NavDropdown>
)
return ( return (
<Box position="relative" ref={ref}> <Box position="relative" ref={ref}>
<Row <Row
...@@ -88,14 +110,14 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => { ...@@ -88,14 +110,14 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => {
{!isSupported ? ( {!isSupported ? (
<> <>
<TokenWarningRedIcon fill={themeVars.colors.darkGray} width={24} height={24} /> <TokenWarningRedIcon fill={themeVars.colors.darkGray} width={24} height={24} />
<Box as="span" className={subhead} style={{ lineHeight: '20px' }}> <Box as="span" className={subhead} display={{ sm: 'none', xl: 'flex' }} style={{ lineHeight: '20px' }}>
{info?.label ?? 'Unsupported'} {info?.label ?? 'Unsupported'}
</Box> </Box>
</> </>
) : ( ) : (
<> <>
<img src={info.logoUrl} alt={info.label} className={styles.Image} /> <img src={info.logoUrl} alt={info.label} className={styles.Image} />
<Box as="span" className={subhead} style={{ lineHeight: '20px' }}> <Box as="span" className={subhead} display={{ sm: 'none', xl: 'flex' }} style={{ lineHeight: '20px' }}>
{info.label} {info.label}
</Box> </Box>
</> </>
...@@ -106,24 +128,7 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => { ...@@ -106,24 +128,7 @@ export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => {
<NewChevronDownIcon width={16} height={16} color="blackBlue" /> <NewChevronDownIcon width={16} height={16} color="blackBlue" />
)} )}
</Row> </Row>
{isOpen && ( {isOpen && (isMobile ? <Portal>{dropdown}</Portal> : <>{dropdown}</>)}
<NavDropdown top={60} leftAligned={isMobile} paddingBottom={8} paddingTop={8}>
<Column marginX="8">
{NETWORK_SELECTOR_CHAINS.map((chainId: SupportedChainId) =>
isSupported ? (
<ChainRow
onSelectChain={async (targetChainId: SupportedChainId) => {
await selectChain(targetChainId)
toggleOpen()
}}
targetChain={chainId}
key={chainId}
/>
) : null
)}
</Column>
</NavDropdown>
)}
</Box> </Box>
) )
} }
import { style } from '@vanilla-extract/css' import { style } from '@vanilla-extract/css'
import { sprinkles } from '../../nft/css/sprinkles.css' import { breakpoints, sprinkles } from '../../nft/css/sprinkles.css'
export const NavDropdown = style([ export const NavDropdown = style([
sprinkles({ sprinkles({
position: 'absolute', position: { sm: 'fixed', md: 'absolute' },
background: 'lightGray', background: 'lightGray',
borderRadius: '12', borderRadius: '12',
borderStyle: 'solid', borderStyle: 'solid',
borderColor: 'medGray', borderColor: 'medGray',
borderWidth: '1px', borderWidth: '1px',
bottom: { sm: '56', md: 'unset' },
}), }),
{ {
boxShadow: '0px 4px 12px 0px #00000026', boxShadow: '0px 4px 12px 0px #00000026',
zIndex: 10, zIndex: 10,
'@media': {
[`screen and (max-width: ${breakpoints.sm}px)`]: {
borderBottomLeftRadius: '0',
borderBottomRightRadius: '0',
},
},
}, },
]) ])
import { Box } from 'nft/components/Box' import { Box } from 'nft/components/Box'
import { useIsMobile } from 'nft/hooks'
import { ReactNode } from 'react' import { ReactNode } from 'react'
import * as styles from './NavDropdown.css' import * as styles from './NavDropdown.css'
...@@ -23,13 +24,14 @@ export const NavDropdown = ({ ...@@ -23,13 +24,14 @@ export const NavDropdown = ({
paddingTop, paddingTop,
children, children,
}: NavDropdownProps) => { }: NavDropdownProps) => {
const isMobile = useIsMobile()
return ( return (
<Box <Box
paddingX={horizontalPadding ? '16' : undefined} paddingX={horizontalPadding ? '16' : undefined}
style={{ style={{
top: `${top}px`, top: isMobile ? 'unset' : `${top}px`,
left: centerHorizontally ? '50%' : leftAligned ? '0px' : 'auto', left: isMobile ? 0 : centerHorizontally ? '50%' : leftAligned ? '0px' : 'auto',
right: centerHorizontally || leftAligned ? 'auto' : '0px', right: isMobile ? 0 : centerHorizontally || leftAligned ? 'auto' : '0px',
transform: centerHorizontally ? 'translateX(-50%)' : 'unset', transform: centerHorizontally ? 'translateX(-50%)' : 'unset',
paddingBottom: paddingBottom ?? '24px', paddingBottom: paddingBottom ?? '24px',
paddingTop: paddingTop ?? '24px', paddingTop: paddingTop ?? '24px',
......
...@@ -43,7 +43,7 @@ const MobileNavbar = () => { ...@@ -43,7 +43,7 @@ const MobileNavbar = () => {
<Box as="a" href="#/swap" className={styles.logoContainer}> <Box as="a" href="#/swap" className={styles.logoContainer}>
<UniIconMobile width="44" height="44" className={styles.logo} /> <UniIconMobile width="44" height="44" className={styles.logo} />
</Box> </Box>
<ChainSwitcher isMobile={true} /> <ChainSwitcher leftAlign={true} />
</Box> </Box>
<Box className={styles.rightSideMobileContainer}> <Box className={styles.rightSideMobileContainer}>
<Row gap="16"> <Row gap="16">
......
...@@ -4,7 +4,6 @@ import { Box } from 'nft/components/Box' ...@@ -4,7 +4,6 @@ import { Box } from 'nft/components/Box'
import { Column, Row } from 'nft/components/Flex' import { Column, Row } from 'nft/components/Flex'
import { vars } from 'nft/css/sprinkles.css' import { vars } from 'nft/css/sprinkles.css'
import { useSearchHistory } from 'nft/hooks' import { useSearchHistory } from 'nft/hooks'
// import { fetchSearchCollections, fetchTrendingCollections } from 'nft/queries'
import { FungibleToken, GenieCollection } from 'nft/types' import { FungibleToken, GenieCollection } from 'nft/types'
import { ethNumberStandardFormatter } from 'nft/utils/currency' import { ethNumberStandardFormatter } from 'nft/utils/currency'
import { putCommas } from 'nft/utils/putCommas' import { putCommas } from 'nft/utils/putCommas'
......
...@@ -112,6 +112,7 @@ const spacing = { ...@@ -112,6 +112,7 @@ const spacing = {
'48': '48px', '48': '48px',
'50': '50px', '50': '50px',
'52': '52px', '52': '52px',
'56': '56px',
'60': '60px', '60': '60px',
'64': '64px', '64': '64px',
'82': '82px', '82': '82px',
......
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