feat: add the phase0 chain switcher (#4376)
* feat: add phase0 chain switcher * update styles * add chain switcher files * remove unneeded eslint disable * add Celo and remove unneeded null check * remove old comment * fix mobile routing Co-authored-by: Charles Bachmeier <charlie@genie.xyz>
This commit is contained in:
parent
de0a716f41
commit
1636786af8
49
src/components/NavBar/ChainSwitcher.css.ts
Normal file
49
src/components/NavBar/ChainSwitcher.css.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
|
||||
import { sprinkles } from '../../nft/css/sprinkles.css'
|
||||
|
||||
export const ChainSwitcher = style([
|
||||
sprinkles({
|
||||
background: 'lightGrayContainer',
|
||||
borderRadius: '8',
|
||||
paddingY: '8',
|
||||
paddingX: '12',
|
||||
cursor: 'pointer',
|
||||
border: 'none',
|
||||
}),
|
||||
])
|
||||
|
||||
export const ChainSwitcherRow = style([
|
||||
sprinkles({
|
||||
border: 'none',
|
||||
color: 'blackBlue',
|
||||
justifyContent: 'space-between',
|
||||
paddingX: '16',
|
||||
paddingY: '12',
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
{
|
||||
lineHeight: '24px',
|
||||
width: '308px',
|
||||
},
|
||||
])
|
||||
|
||||
export const Image = style([
|
||||
sprinkles({
|
||||
width: '28',
|
||||
height: '28',
|
||||
}),
|
||||
])
|
||||
|
||||
export const Icon = style([
|
||||
Image,
|
||||
sprinkles({
|
||||
marginRight: '12',
|
||||
}),
|
||||
])
|
||||
|
||||
export const Indicator = style([
|
||||
sprinkles({
|
||||
marginLeft: '8',
|
||||
}),
|
||||
])
|
108
src/components/NavBar/ChainSwitcher.tsx
Normal file
108
src/components/NavBar/ChainSwitcher.tsx
Normal file
@ -0,0 +1,108 @@
|
||||
import { useWeb3React } from '@web3-react/core'
|
||||
import { getChainInfo } from 'constants/chainInfo'
|
||||
import { SupportedChainId } from 'constants/chains'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import useSelectChain from 'hooks/useSelectChain'
|
||||
import useSyncChainQuery from 'hooks/useSyncChainQuery'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Column, Row } from 'nft/components/Flex'
|
||||
import { NewChevronDownIcon, NewChevronUpIcon } from 'nft/components/icons'
|
||||
import { CheckMarkIcon } from 'nft/components/icons'
|
||||
import { subhead } from 'nft/css/common.css'
|
||||
import { ReactNode, useReducer, useRef } from 'react'
|
||||
import { isChainAllowed } from 'utils/switchChain'
|
||||
|
||||
import * as styles from './ChainSwitcher.css'
|
||||
import { NavDropdown } from './NavDropdown'
|
||||
|
||||
const ChainRow = ({
|
||||
targetChain,
|
||||
onSelectChain,
|
||||
}: {
|
||||
targetChain: SupportedChainId
|
||||
onSelectChain: (targetChain: number) => void
|
||||
}) => {
|
||||
const { chainId } = useWeb3React()
|
||||
const active = chainId === targetChain
|
||||
const { label, logoUrl } = getChainInfo(targetChain)
|
||||
|
||||
return (
|
||||
<Row
|
||||
as="button"
|
||||
background={active ? 'lightGrayContainer' : 'none'}
|
||||
className={`${styles.ChainSwitcherRow} ${subhead}`}
|
||||
onClick={() => onSelectChain(targetChain)}
|
||||
>
|
||||
<ChainDetails>
|
||||
<img src={logoUrl} alt={label} className={styles.Icon} />
|
||||
{label}
|
||||
</ChainDetails>
|
||||
{active && <CheckMarkIcon width={20} height={20} />}
|
||||
</Row>
|
||||
)
|
||||
}
|
||||
|
||||
const ChainDetails = ({ children }: { children: ReactNode }) => <Row>{children}</Row>
|
||||
|
||||
const NETWORK_SELECTOR_CHAINS = [
|
||||
SupportedChainId.MAINNET,
|
||||
SupportedChainId.POLYGON,
|
||||
SupportedChainId.OPTIMISM,
|
||||
SupportedChainId.ARBITRUM_ONE,
|
||||
SupportedChainId.CELO,
|
||||
]
|
||||
|
||||
interface ChainSwitcherProps {
|
||||
isMobile?: boolean
|
||||
}
|
||||
|
||||
export const ChainSwitcher = ({ isMobile }: ChainSwitcherProps) => {
|
||||
const { chainId, connector } = useWeb3React()
|
||||
const [isOpen, toggleOpen] = useReducer((s) => !s, false)
|
||||
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
useOnClickOutside(ref, isOpen ? toggleOpen : undefined)
|
||||
|
||||
const info = chainId ? getChainInfo(chainId) : undefined
|
||||
|
||||
const selectChain = useSelectChain()
|
||||
useSyncChainQuery()
|
||||
|
||||
if (!chainId || !info) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Box position="relative" ref={ref}>
|
||||
<Row as="button" gap="8" className={styles.ChainSwitcher} onClick={toggleOpen}>
|
||||
<img src={info.logoUrl} alt={info.label} className={styles.Image} />
|
||||
<Box as="span" className={subhead} color="explicitWhite" style={{ lineHeight: '20px' }}>
|
||||
{info.label}
|
||||
</Box>
|
||||
{isOpen ? (
|
||||
<NewChevronUpIcon width={16} height={16} color="darkGray" />
|
||||
) : (
|
||||
<NewChevronDownIcon width={16} height={16} color="darkGray" />
|
||||
)}
|
||||
</Row>
|
||||
{isOpen && (
|
||||
<NavDropdown top={60} leftAligned={isMobile}>
|
||||
<Column gap="4">
|
||||
{NETWORK_SELECTOR_CHAINS.map((chainId: SupportedChainId) =>
|
||||
isChainAllowed(connector, chainId) ? (
|
||||
<ChainRow
|
||||
onSelectChain={async (targetChainId: SupportedChainId) => {
|
||||
await selectChain(targetChainId)
|
||||
toggleOpen()
|
||||
}}
|
||||
targetChain={chainId}
|
||||
key={chainId}
|
||||
/>
|
||||
) : null
|
||||
)}
|
||||
</Column>
|
||||
</NavDropdown>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
@ -159,7 +159,7 @@ export const MobileSideBar = () => {
|
||||
<NavLinkRow href="/swap" close={toggleOpen} isActive={pathname.startsWith('/swap')}>
|
||||
Swap
|
||||
</NavLinkRow>
|
||||
<NavLinkRow href="/explore" close={toggleOpen} isActive={pathname.startsWith('/explore')}>
|
||||
<NavLinkRow href="/tokens" close={toggleOpen} isActive={pathname.startsWith('/tokens')}>
|
||||
Tokens
|
||||
</NavLinkRow>
|
||||
<NavLinkRow href="/pool" id={'pool-nav-link'} isActive={isPoolActive} close={toggleOpen}>
|
||||
|
@ -7,6 +7,7 @@ import { Box } from '../../nft/components/Box'
|
||||
import { Row } from '../../nft/components/Flex'
|
||||
import { UniIcon, UniIconMobile } from '../../nft/components/icons'
|
||||
import { breakpoints } from '../../nft/css/sprinkles.css'
|
||||
import { ChainSwitcher } from './ChainSwitcher'
|
||||
import { MenuDropdown } from './MenuDropdown'
|
||||
import { MobileSideBar } from './MobileSidebar'
|
||||
import * as styles from './Navbar.css'
|
||||
@ -40,7 +41,7 @@ const MobileNavbar = () => {
|
||||
<Box as="a" href="#/swap" className={styles.logoContainer}>
|
||||
<UniIconMobile width="44" height="44" className={styles.logo} />
|
||||
</Box>
|
||||
{/* TODO add ChainSwitcher */}
|
||||
<ChainSwitcher isMobile={true} />
|
||||
</Box>
|
||||
<Box className={styles.rightSideMobileContainer}>
|
||||
<Row gap="16">
|
||||
@ -95,7 +96,7 @@ const Navbar = () => {
|
||||
<Box className={styles.rightSideContainer}>
|
||||
<Row gap="12">
|
||||
<MenuDropdown />
|
||||
{/* TODO add ChainSwitcher */}
|
||||
<ChainSwitcher />
|
||||
<Web3Status />
|
||||
</Row>
|
||||
</Box>
|
||||
|
Loading…
Reference in New Issue
Block a user