feat: Mobile Nav (#4501)
* working and cleaned up mobile nav * delete old files * fix wallet position * update searchbar breakpoint * update full screen search * delete old comments * cleanup eslint * Update MenuDropdown.tsx * Update SearchBar.tsx Co-authored-by: Charlie <charlie@uniswap.org>
This commit is contained in:
parent
748a5eadc0
commit
751ce8e6d6
@ -79,7 +79,7 @@ export const ChainSwitcher = ({ leftAlign }: ChainSwitcherProps) => {
|
||||
const isSupported = !!info
|
||||
|
||||
const dropdown = (
|
||||
<NavDropdown top={54} leftAligned={leftAlign} paddingBottom={8} paddingTop={8}>
|
||||
<NavDropdown top="56" left="0">
|
||||
<Column marginX="8">
|
||||
{NETWORK_SELECTOR_CHAINS.map((chainId: SupportedChainId) => (
|
||||
<ChainRow
|
||||
|
@ -62,6 +62,6 @@ export const Separator = style([
|
||||
export const IconRow = style([
|
||||
sprinkles({
|
||||
paddingX: '16',
|
||||
marginTop: '4',
|
||||
justifyContent: { sm: 'center', md: 'flex-start' },
|
||||
}),
|
||||
])
|
||||
|
@ -129,7 +129,7 @@ export const MenuDropdown = () => {
|
||||
</NavIcon>
|
||||
|
||||
{isOpen && (
|
||||
<NavDropdown top={60}>
|
||||
<NavDropdown top={{ sm: 'unset', xxl: '56' }} bottom={{ sm: '56', xxl: 'unset' }} right="0">
|
||||
<Column gap="16">
|
||||
<Column paddingX="8" gap="4">
|
||||
{nftFlag === NftVariant.Enabled && (
|
||||
@ -154,7 +154,13 @@ export const MenuDropdown = () => {
|
||||
</PrimaryMenuRow>
|
||||
</Column>
|
||||
<Separator />
|
||||
<Column paddingX="8">
|
||||
<Box
|
||||
display="flex"
|
||||
flexDirection={{ sm: 'row', md: 'column' }}
|
||||
flexWrap="wrap"
|
||||
alignItems={{ sm: 'center', md: 'flex-start' }}
|
||||
paddingX="8"
|
||||
>
|
||||
<SecondaryLinkedText href="https://help.uniswap.org/en/">Help center ↗</SecondaryLinkedText>
|
||||
<SecondaryLinkedText href="https://docs.uniswap.org/">Documentation ↗</SecondaryLinkedText>
|
||||
<SecondaryLinkedText
|
||||
@ -166,7 +172,7 @@ export const MenuDropdown = () => {
|
||||
{(isDevelopmentEnv() || isStagingEnv()) && (
|
||||
<SecondaryLinkedText onClick={openFeatureFlagsModal}>{`Feature Flags`}</SecondaryLinkedText>
|
||||
)}
|
||||
</Column>
|
||||
</Box>
|
||||
<IconRow>
|
||||
<Icon href="https://discord.com/invite/FCfyBSbCU5">
|
||||
<DiscordIconMenu className={styles.hover} width={24} height={24} color={themeVars.colors.darkGray} />
|
||||
|
@ -1,121 +0,0 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
import { subhead } from 'nft/css/common.css'
|
||||
|
||||
import { sprinkles } from '../../nft/css/sprinkles.css'
|
||||
|
||||
export const sidebar = style([
|
||||
sprinkles({
|
||||
display: 'flex',
|
||||
position: 'fixed',
|
||||
background: 'white',
|
||||
height: 'full',
|
||||
top: '0',
|
||||
left: '0',
|
||||
right: '0',
|
||||
bottom: '0',
|
||||
paddingBottom: '16',
|
||||
justifyContent: 'space-between',
|
||||
}),
|
||||
{
|
||||
zIndex: 20,
|
||||
},
|
||||
])
|
||||
|
||||
export const icon = style([
|
||||
sprinkles({
|
||||
width: '32',
|
||||
height: '32',
|
||||
}),
|
||||
])
|
||||
|
||||
export const iconContainer = style([
|
||||
sprinkles({
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
color: 'darkGray',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
justifyContent: 'flex-end',
|
||||
textAlign: 'center',
|
||||
cursor: 'pointer',
|
||||
padding: '6',
|
||||
}),
|
||||
])
|
||||
|
||||
export const linkRow = style([
|
||||
subhead,
|
||||
sprinkles({
|
||||
color: 'blackBlue',
|
||||
width: 'full',
|
||||
paddingLeft: '16',
|
||||
paddingY: '12',
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
{
|
||||
lineHeight: '24px',
|
||||
textDecoration: 'none',
|
||||
},
|
||||
])
|
||||
|
||||
export const activeLinkRow = style([
|
||||
linkRow,
|
||||
sprinkles({
|
||||
background: 'lightGrayButton',
|
||||
}),
|
||||
])
|
||||
|
||||
export const separator = style([
|
||||
sprinkles({
|
||||
height: '0',
|
||||
borderStyle: 'solid',
|
||||
borderColor: 'medGray',
|
||||
borderWidth: '1px',
|
||||
marginY: '8',
|
||||
marginX: '16',
|
||||
}),
|
||||
])
|
||||
|
||||
export const extraLinkRow = style([
|
||||
subhead,
|
||||
sprinkles({
|
||||
width: 'full',
|
||||
color: 'blackBlue',
|
||||
paddingY: '12',
|
||||
paddingLeft: '16',
|
||||
cursor: 'pointer',
|
||||
}),
|
||||
{
|
||||
lineHeight: '24px',
|
||||
textDecoration: 'none',
|
||||
},
|
||||
])
|
||||
|
||||
export const bottomExternalLinks = style([
|
||||
sprinkles({
|
||||
gap: '4',
|
||||
paddingX: '4',
|
||||
width: 'max',
|
||||
flexWrap: 'wrap',
|
||||
}),
|
||||
])
|
||||
|
||||
export const bottomJointExternalLinksContainer = style([
|
||||
sprinkles({
|
||||
paddingX: '8',
|
||||
paddingY: '4',
|
||||
color: 'darkGray',
|
||||
fontWeight: 'medium',
|
||||
fontSize: '12',
|
||||
}),
|
||||
{
|
||||
lineHeight: '20px',
|
||||
},
|
||||
])
|
||||
|
||||
export const IconRow = style([
|
||||
sprinkles({
|
||||
gap: '12',
|
||||
width: 'max',
|
||||
}),
|
||||
])
|
@ -1,249 +0,0 @@
|
||||
import FeatureFlagModal from 'components/FeatureFlagModal/FeatureFlagModal'
|
||||
import { PrivacyPolicyModal } from 'components/PrivacyPolicy'
|
||||
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Portal } from 'nft/components/common/Portal'
|
||||
import { Column, Row } from 'nft/components/Flex'
|
||||
import {
|
||||
BarChartIconMobile,
|
||||
BulletIcon,
|
||||
CloseIcon,
|
||||
DiscordIconMenuMobile,
|
||||
GithubIconMenuMobile,
|
||||
GovernanceIconMobile,
|
||||
HamburgerIcon,
|
||||
ThinTagIconMobile,
|
||||
TwitterIconMenuMobile,
|
||||
} from 'nft/components/icons'
|
||||
import { themeVars } from 'nft/css/sprinkles.css'
|
||||
import { ReactNode, useReducer } from 'react'
|
||||
import { NavLink, NavLinkProps, useLocation } from 'react-router-dom'
|
||||
import { useToggleModal, useTogglePrivacyPolicy } from 'state/application/hooks'
|
||||
import { ApplicationModal } from 'state/application/reducer'
|
||||
import { isDevelopmentEnv, isStagingEnv } from 'utils/env'
|
||||
|
||||
import * as styles from './MobileSidebar.css'
|
||||
import { NavIcon } from './NavIcon'
|
||||
|
||||
interface NavLinkRowProps {
|
||||
href: string
|
||||
id?: NavLinkProps['id']
|
||||
isActive?: boolean
|
||||
close: () => void
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
const NavLinkRow = ({ href, id, isActive, close, children }: NavLinkRowProps) => {
|
||||
return (
|
||||
<NavLink to={href} className={isActive ? styles.activeLinkRow : styles.linkRow} id={id} onClick={close}>
|
||||
{children}
|
||||
</NavLink>
|
||||
)
|
||||
}
|
||||
|
||||
const ExtraLinkRow = ({
|
||||
to,
|
||||
href,
|
||||
close,
|
||||
children,
|
||||
}: {
|
||||
to?: NavLinkProps['to']
|
||||
href?: string
|
||||
close: () => void
|
||||
children: ReactNode
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
{to ? (
|
||||
<NavLink to={to} className={styles.extraLinkRow}>
|
||||
<Row gap="12" onClick={close}>
|
||||
{children}
|
||||
</Row>
|
||||
</NavLink>
|
||||
) : (
|
||||
<Row
|
||||
as="a"
|
||||
href={href}
|
||||
target={'_blank'}
|
||||
rel={'noopener noreferrer'}
|
||||
gap="12"
|
||||
onClick={close}
|
||||
className={styles.extraLinkRow}
|
||||
>
|
||||
{children}
|
||||
</Row>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const BottomExternalLink = ({
|
||||
href,
|
||||
onClick,
|
||||
children,
|
||||
}: {
|
||||
href?: string
|
||||
onClick?: () => void
|
||||
children: ReactNode
|
||||
}) => {
|
||||
return (
|
||||
<Box
|
||||
as={href ? 'a' : 'div'}
|
||||
href={href ?? undefined}
|
||||
target={href ? '_blank' : undefined}
|
||||
rel={href ? 'noopener noreferrer' : undefined}
|
||||
className={`${styles.bottomJointExternalLinksContainer}`}
|
||||
onClick={onClick}
|
||||
cursor="pointer"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
const Icon = ({ href, children }: { href?: string; children: ReactNode }) => {
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
as={href ? 'a' : 'div'}
|
||||
href={href ?? undefined}
|
||||
target={href ? '_blank' : undefined}
|
||||
rel={href ? 'noopener noreferrer' : undefined}
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
color="blackBlue"
|
||||
background="none"
|
||||
border="none"
|
||||
justifyContent="center"
|
||||
textAlign="center"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const IconRow = ({ children }: { children: ReactNode }) => {
|
||||
return <Row className={styles.IconRow}>{children}</Row>
|
||||
}
|
||||
|
||||
const Seperator = () => {
|
||||
return <Box className={styles.separator} />
|
||||
}
|
||||
|
||||
export const MobileSideBar = () => {
|
||||
const [isOpen, toggleOpen] = useReducer((s) => !s, false)
|
||||
const togglePrivacyPolicy = useTogglePrivacyPolicy()
|
||||
const openFeatureFlagsModal = useToggleModal(ApplicationModal.FEATURE_FLAGS)
|
||||
const { pathname } = useLocation()
|
||||
const nftFlag = useNftFlag()
|
||||
const isPoolActive =
|
||||
pathname.startsWith('/pool') ||
|
||||
pathname.startsWith('/add') ||
|
||||
pathname.startsWith('/remove') ||
|
||||
pathname.startsWith('/increase') ||
|
||||
pathname.startsWith('/find')
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavIcon isActive={isOpen} onClick={toggleOpen}>
|
||||
<HamburgerIcon width={28} height={28} />
|
||||
</NavIcon>
|
||||
{isOpen && (
|
||||
<Portal>
|
||||
<Column className={styles.sidebar}>
|
||||
<Column>
|
||||
<Row justifyContent="flex-end" marginTop="14" marginBottom="20" marginRight="8">
|
||||
<Box as="button" onClick={toggleOpen} className={styles.iconContainer}>
|
||||
<CloseIcon className={styles.icon} />
|
||||
</Box>
|
||||
</Row>
|
||||
<Column gap="4">
|
||||
<NavLinkRow href="/swap" close={toggleOpen} isActive={pathname.startsWith('/swap')}>
|
||||
Swap
|
||||
</NavLinkRow>
|
||||
<NavLinkRow href="/tokens" close={toggleOpen} isActive={pathname.startsWith('/tokens')}>
|
||||
Tokens
|
||||
</NavLinkRow>
|
||||
{nftFlag === NftVariant.Enabled && (
|
||||
<NavLinkRow href="/nfts" close={toggleOpen} isActive={pathname.startsWith('/nfts')}>
|
||||
NFTs
|
||||
</NavLinkRow>
|
||||
)}
|
||||
<NavLinkRow href="/pool" id={'pool-nav-link'} isActive={isPoolActive} close={toggleOpen}>
|
||||
Pool
|
||||
</NavLinkRow>
|
||||
</Column>
|
||||
<Seperator />
|
||||
<Column gap="4">
|
||||
{nftFlag === NftVariant.Enabled && (
|
||||
<ExtraLinkRow to="/nft/sell" close={toggleOpen}>
|
||||
<Icon>
|
||||
<ThinTagIconMobile width={24} height={24} />
|
||||
</Icon>
|
||||
Sell NFTs
|
||||
</ExtraLinkRow>
|
||||
)}
|
||||
<ExtraLinkRow to="/vote" close={toggleOpen}>
|
||||
<Icon>
|
||||
<GovernanceIconMobile width={24} height={24} />
|
||||
</Icon>
|
||||
Vote in governance
|
||||
</ExtraLinkRow>
|
||||
<ExtraLinkRow href="https://info.uniswap.org/#/" close={toggleOpen}>
|
||||
<Icon>
|
||||
<BarChartIconMobile width={24} height={24} />
|
||||
</Icon>
|
||||
View token analytics ↗
|
||||
</ExtraLinkRow>
|
||||
</Column>
|
||||
</Column>
|
||||
<Column>
|
||||
<Row justifyContent="center" marginBottom="12" flexWrap="wrap">
|
||||
<Row className={styles.bottomExternalLinks}>
|
||||
<BottomExternalLink href="https://help.uniswap.org/en/" onClick={toggleOpen}>
|
||||
Help center ↗
|
||||
</BottomExternalLink>
|
||||
<BulletIcon />
|
||||
<BottomExternalLink href="https://docs.uniswap.org/" onClick={toggleOpen}>
|
||||
Documentation ↗
|
||||
</BottomExternalLink>
|
||||
<BulletIcon />
|
||||
<BottomExternalLink
|
||||
onClick={() => {
|
||||
toggleOpen()
|
||||
togglePrivacyPolicy()
|
||||
}}
|
||||
>
|
||||
{`Legal & Privacy`}
|
||||
</BottomExternalLink>
|
||||
</Row>
|
||||
{(isDevelopmentEnv() || isStagingEnv()) && (
|
||||
<>
|
||||
<BulletIcon />
|
||||
<BottomExternalLink onClick={openFeatureFlagsModal}>{`Feature Flags`}</BottomExternalLink>
|
||||
</>
|
||||
)}
|
||||
</Row>
|
||||
<Row justifyContent="center">
|
||||
<IconRow>
|
||||
<Icon href="https://discord.com/invite/FCfyBSbCU5">
|
||||
<DiscordIconMenuMobile width={32} height={32} color={themeVars.colors.darkGray} />
|
||||
</Icon>
|
||||
<Icon href="https://twitter.com/Uniswap">
|
||||
<TwitterIconMenuMobile width={32} height={32} color={themeVars.colors.darkGray} />
|
||||
</Icon>
|
||||
<Icon href="https://github.com/Uniswap">
|
||||
<GithubIconMenuMobile width={32} height={32} color={themeVars.colors.darkGray} />
|
||||
</Icon>
|
||||
</IconRow>
|
||||
</Row>
|
||||
</Column>
|
||||
</Column>
|
||||
</Portal>
|
||||
)}
|
||||
<PrivacyPolicyModal />
|
||||
<FeatureFlagModal />
|
||||
</>
|
||||
)
|
||||
}
|
@ -1,25 +1,40 @@
|
||||
import { style } from '@vanilla-extract/css'
|
||||
|
||||
import { breakpoints, sprinkles } from '../../nft/css/sprinkles.css'
|
||||
import { sprinkles } from '../../nft/css/sprinkles.css'
|
||||
|
||||
export const NavDropdown = style([
|
||||
const baseNavDropdown = style([
|
||||
sprinkles({
|
||||
position: { sm: 'fixed', md: 'absolute' },
|
||||
background: 'lightGray',
|
||||
borderRadius: '12',
|
||||
borderStyle: 'solid',
|
||||
borderColor: 'medGray',
|
||||
borderWidth: '1px',
|
||||
bottom: { sm: '56', md: 'unset' },
|
||||
paddingBottom: '8',
|
||||
paddingTop: '8',
|
||||
}),
|
||||
{
|
||||
boxShadow: '0px 4px 12px 0px #00000026',
|
||||
zIndex: 10,
|
||||
'@media': {
|
||||
[`screen and (max-width: ${breakpoints.sm}px)`]: {
|
||||
borderBottomLeftRadius: '0',
|
||||
borderBottomRightRadius: '0',
|
||||
},
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
export const NavDropdown = style([
|
||||
baseNavDropdown,
|
||||
sprinkles({
|
||||
position: 'absolute',
|
||||
borderRadius: '12',
|
||||
}),
|
||||
{},
|
||||
])
|
||||
|
||||
export const mobileNavDropdown = style([
|
||||
baseNavDropdown,
|
||||
sprinkles({
|
||||
position: 'fixed',
|
||||
borderTopRightRadius: '12',
|
||||
borderTopLeftRadius: '12',
|
||||
top: 'unset',
|
||||
bottom: '56',
|
||||
left: '0',
|
||||
right: '0',
|
||||
}),
|
||||
])
|
||||
|
@ -1,45 +1,12 @@
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Box, BoxProps } from 'nft/components/Box'
|
||||
import { useIsMobile } from 'nft/hooks'
|
||||
import { ReactNode } from 'react'
|
||||
import { ForwardedRef, forwardRef } from 'react'
|
||||
|
||||
import * as styles from './NavDropdown.css'
|
||||
|
||||
interface NavDropdownProps {
|
||||
top: number
|
||||
right?: number
|
||||
leftAligned?: boolean
|
||||
horizontalPadding?: boolean
|
||||
centerHorizontally?: boolean
|
||||
paddingBottom?: number
|
||||
paddingTop?: number
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const NavDropdown = ({
|
||||
top,
|
||||
centerHorizontally,
|
||||
leftAligned,
|
||||
horizontalPadding,
|
||||
paddingBottom,
|
||||
paddingTop,
|
||||
children,
|
||||
}: NavDropdownProps) => {
|
||||
export const NavDropdown = forwardRef((props: BoxProps, ref: ForwardedRef<HTMLElement>) => {
|
||||
const isMobile = useIsMobile()
|
||||
return (
|
||||
<Box
|
||||
paddingX={horizontalPadding ? '16' : undefined}
|
||||
style={{
|
||||
top: isMobile ? 'unset' : `${top}px`,
|
||||
left: isMobile ? 0 : centerHorizontally ? '50%' : leftAligned ? '0px' : 'auto',
|
||||
right: isMobile ? 0 : centerHorizontally || leftAligned ? 'auto' : '0px',
|
||||
transform: centerHorizontally ? 'translateX(-50%)' : 'unset',
|
||||
paddingBottom: paddingBottom ?? '24px',
|
||||
paddingTop: paddingTop ?? '24px',
|
||||
zIndex: 3,
|
||||
}}
|
||||
className={styles.NavDropdown}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
return <Box ref={ref} className={isMobile ? styles.mobileNavDropdown : styles.NavDropdown} {...props} />
|
||||
})
|
||||
|
||||
NavDropdown.displayName = 'NavDropdown'
|
||||
|
@ -7,7 +7,6 @@ export const navIcon = style([
|
||||
position: 'relative',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
color: 'blackBlue',
|
||||
border: 'none',
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
|
@ -11,7 +11,13 @@ interface NavIconProps {
|
||||
|
||||
export const NavIcon = ({ children, isActive, onClick }: NavIconProps) => {
|
||||
return (
|
||||
<Box as="button" className={styles.navIcon} background={isActive ? 'accentActiveSoft' : 'none'} onClick={onClick}>
|
||||
<Box
|
||||
as="button"
|
||||
className={styles.navIcon}
|
||||
background={isActive ? 'accentActiveSoft' : 'none'}
|
||||
color={isActive ? 'blackBlue' : 'darkGray'}
|
||||
onClick={onClick}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
)
|
||||
|
@ -38,15 +38,6 @@ export const baseContainer = style([
|
||||
}),
|
||||
])
|
||||
|
||||
export const baseMobileContainer = style([
|
||||
sprinkles({
|
||||
display: 'flex',
|
||||
width: 'full',
|
||||
alignItems: 'center',
|
||||
marginY: '2',
|
||||
}),
|
||||
])
|
||||
|
||||
export const baseSideContainer = style([
|
||||
baseContainer,
|
||||
sprinkles({
|
||||
@ -64,19 +55,13 @@ export const leftSideContainer = style([
|
||||
}),
|
||||
])
|
||||
|
||||
export const leftSideMobileContainer = style([
|
||||
baseMobileContainer,
|
||||
sprinkles({
|
||||
justifyContent: 'flex-start',
|
||||
}),
|
||||
])
|
||||
|
||||
export const middleContainer = style([
|
||||
baseContainer,
|
||||
sprinkles({
|
||||
flex: '1',
|
||||
flexShrink: '1',
|
||||
justifyContent: 'center',
|
||||
display: { sm: 'none', lg: 'flex' },
|
||||
}),
|
||||
])
|
||||
|
||||
@ -95,6 +80,7 @@ const baseMenuItem = style([
|
||||
marginY: '4',
|
||||
borderRadius: '12',
|
||||
transition: '250',
|
||||
height: 'min',
|
||||
}),
|
||||
{
|
||||
lineHeight: '24px',
|
||||
@ -112,13 +98,6 @@ export const menuItem = style([
|
||||
}),
|
||||
])
|
||||
|
||||
export const rightSideMobileContainer = style([
|
||||
baseMobileContainer,
|
||||
sprinkles({
|
||||
justifyContent: 'flex-end',
|
||||
}),
|
||||
])
|
||||
|
||||
export const activeMenuItem = style([
|
||||
baseMenuItem,
|
||||
sprinkles({
|
||||
@ -127,16 +106,17 @@ export const activeMenuItem = style([
|
||||
}),
|
||||
])
|
||||
|
||||
export const mobileWalletContainer = style([
|
||||
export const mobileBottomBar = style([
|
||||
sprinkles({
|
||||
position: 'fixed',
|
||||
display: 'flex',
|
||||
display: { sm: 'flex', xxl: 'none' },
|
||||
bottom: '0',
|
||||
right: '1/2',
|
||||
marginY: '0',
|
||||
marginX: 'auto',
|
||||
right: '0',
|
||||
left: '0',
|
||||
justifyContent: 'space-between',
|
||||
paddingY: '4',
|
||||
paddingX: '8',
|
||||
height: '56',
|
||||
background: 'lightGray',
|
||||
}),
|
||||
{
|
||||
transform: 'translate(50%,-50%)',
|
||||
},
|
||||
])
|
||||
|
@ -1,16 +1,13 @@
|
||||
import Web3Status from 'components/Web3Status'
|
||||
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
|
||||
import { useWindowSize } from 'hooks/useWindowSize'
|
||||
import { ReactNode } from 'react'
|
||||
import { NavLink, NavLinkProps, useLocation } from 'react-router-dom'
|
||||
|
||||
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 { UniIcon } from '../../nft/components/icons'
|
||||
import { ChainSwitcher } from './ChainSwitcher'
|
||||
import { MenuDropdown } from './MenuDropdown'
|
||||
import { MobileSideBar } from './MobileSidebar'
|
||||
import * as styles from './Navbar.css'
|
||||
import { SearchBar } from './SearchBar'
|
||||
|
||||
@ -34,46 +31,10 @@ const MenuItem = ({ href, id, isActive, children }: MenuItemProps) => {
|
||||
)
|
||||
}
|
||||
|
||||
const MobileNavbar = () => {
|
||||
return (
|
||||
<>
|
||||
<nav className={styles.nav}>
|
||||
<Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch">
|
||||
<Box className={styles.leftSideMobileContainer}>
|
||||
<Box as="a" href="#/swap" className={styles.logoContainer}>
|
||||
<UniIconMobile width="44" height="44" className={styles.logo} />
|
||||
</Box>
|
||||
<ChainSwitcher leftAlign={true} />
|
||||
</Box>
|
||||
<Box className={styles.middleContainer} display={{ sm: 'none', md: 'flex' }}>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box className={styles.rightSideMobileContainer}>
|
||||
<Row gap="16">
|
||||
<Box display={{ sm: 'flex', md: 'none' }}>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<MobileSideBar />
|
||||
</Row>
|
||||
</Box>
|
||||
</Box>
|
||||
</nav>
|
||||
<Box className={styles.mobileWalletContainer}>
|
||||
<Web3Status />
|
||||
</Box>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Navbar = () => {
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
const PageTabs = () => {
|
||||
const { pathname } = useLocation()
|
||||
const nftFlag = useNftFlag()
|
||||
|
||||
if (windowWidth && windowWidth <= breakpoints.xl) {
|
||||
return <MobileNavbar />
|
||||
}
|
||||
|
||||
const isPoolActive =
|
||||
pathname.startsWith('/pool') ||
|
||||
pathname.startsWith('/add') ||
|
||||
@ -82,41 +43,66 @@ const Navbar = () => {
|
||||
pathname.startsWith('/find')
|
||||
|
||||
return (
|
||||
<nav className={styles.nav}>
|
||||
<Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch">
|
||||
<Box className={styles.leftSideContainer}>
|
||||
<Box as="a" href="#/swap" className={styles.logoContainer}>
|
||||
<UniIcon width="48" height="48" className={styles.logo} />
|
||||
<>
|
||||
<MenuItem href="/swap" isActive={pathname.startsWith('/swap')}>
|
||||
Swap
|
||||
</MenuItem>
|
||||
<MenuItem href="/tokens" isActive={pathname.startsWith('/tokens')}>
|
||||
Tokens
|
||||
</MenuItem>
|
||||
{nftFlag === NftVariant.Enabled && (
|
||||
<MenuItem href="/nfts" isActive={pathname.startsWith('/nfts')}>
|
||||
NFTs
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem href="/pool" id={'pool-nav-link'} isActive={isPoolActive}>
|
||||
Pool
|
||||
</MenuItem>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Navbar = () => {
|
||||
return (
|
||||
<>
|
||||
<nav className={styles.nav}>
|
||||
<Box display="flex" height="full" flexWrap="nowrap" alignItems="stretch">
|
||||
<Box className={styles.leftSideContainer}>
|
||||
<Box as="a" href="#/swap" className={styles.logoContainer}>
|
||||
<UniIcon width="48" height="48" className={styles.logo} />
|
||||
</Box>
|
||||
<Box display={{ sm: 'flex', xxl: 'none' }}>
|
||||
<ChainSwitcher leftAlign={true} />
|
||||
</Box>
|
||||
<Row gap="8" display={{ sm: 'none', xxl: 'flex' }}>
|
||||
<PageTabs />
|
||||
</Row>
|
||||
</Box>
|
||||
<Box className={styles.middleContainer}>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box className={styles.rightSideContainer}>
|
||||
<Row gap="12">
|
||||
<Box display={{ sm: 'flex', lg: 'none' }}>
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box display={{ sm: 'none', xxl: 'flex' }}>
|
||||
<MenuDropdown />
|
||||
</Box>
|
||||
<Box display={{ sm: 'none', xxl: 'flex' }}>
|
||||
<ChainSwitcher />
|
||||
</Box>
|
||||
|
||||
<Web3Status />
|
||||
</Row>
|
||||
</Box>
|
||||
<Row gap="8">
|
||||
<MenuItem href="/swap" isActive={pathname.startsWith('/swap')}>
|
||||
Swap
|
||||
</MenuItem>
|
||||
<MenuItem href="/tokens" isActive={pathname.startsWith('/tokens')}>
|
||||
Tokens
|
||||
</MenuItem>
|
||||
{nftFlag === NftVariant.Enabled && (
|
||||
<MenuItem href="/nfts" isActive={pathname.startsWith('/nfts')}>
|
||||
NFTs
|
||||
</MenuItem>
|
||||
)}
|
||||
<MenuItem href="/pool" id={'pool-nav-link'} isActive={isPoolActive}>
|
||||
Pool
|
||||
</MenuItem>
|
||||
</Row>
|
||||
</Box>
|
||||
<Box className={styles.middleContainer} display="flex">
|
||||
<SearchBar />
|
||||
</Box>
|
||||
<Box className={styles.rightSideContainer}>
|
||||
<Row gap="12">
|
||||
<MenuDropdown />
|
||||
<ChainSwitcher />
|
||||
<Web3Status />
|
||||
</Row>
|
||||
</Box>
|
||||
</nav>
|
||||
<Box className={styles.mobileBottomBar}>
|
||||
<PageTabs />
|
||||
<MenuDropdown />
|
||||
</Box>
|
||||
</nav>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ const baseSearchStyle = style([
|
||||
}),
|
||||
{
|
||||
'@media': {
|
||||
[`screen and (min-width: ${breakpoints.sm}px)`]: {
|
||||
[`screen and (min-width: ${breakpoints.md}px)`]: {
|
||||
width: DESKTOP_NAVBAR_WIDTH,
|
||||
},
|
||||
},
|
||||
|
@ -2,14 +2,12 @@ import clsx from 'clsx'
|
||||
import { NftVariant, useNftFlag } from 'featureFlags/flags/nft'
|
||||
import useDebounce from 'hooks/useDebounce'
|
||||
import { useOnClickOutside } from 'hooks/useOnClickOutside'
|
||||
import { useWindowSize } from 'hooks/useWindowSize'
|
||||
import { organizeSearchResults } from 'lib/utils/searchBar'
|
||||
import { Box } from 'nft/components/Box'
|
||||
import { Column, Row } from 'nft/components/Flex'
|
||||
import { Overlay } from 'nft/components/modals/Overlay'
|
||||
import { magicalGradientOnHover, subheadSmall } from 'nft/css/common.css'
|
||||
import { breakpoints } from 'nft/css/sprinkles.css'
|
||||
import { useSearchHistory } from 'nft/hooks'
|
||||
import { useIsMobile, useSearchHistory } from 'nft/hooks'
|
||||
import { fetchSearchCollections, fetchTrendingCollections } from 'nft/queries'
|
||||
import { fetchSearchTokens } from 'nft/queries/genie/SearchTokensFetcher'
|
||||
import { fetchTrendingTokens } from 'nft/queries/genie/TrendingTokensFetcher'
|
||||
@ -267,8 +265,8 @@ export const SearchBar = () => {
|
||||
const debouncedSearchValue = useDebounce(searchValue, 300)
|
||||
const searchRef = useRef<HTMLDivElement>(null)
|
||||
const { pathname } = useLocation()
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
const phase1Flag = useNftFlag()
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
useOnClickOutside(searchRef, () => {
|
||||
isOpen && toggleOpen()
|
||||
@ -318,15 +316,13 @@ export const SearchBar = () => {
|
||||
setSearchValue('')
|
||||
}, [pathname])
|
||||
|
||||
const isMobile = useMemo(() => windowWidth && windowWidth <= breakpoints.sm, [windowWidth])
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
position={{ sm: isOpen ? 'absolute' : 'relative', md: 'relative' }}
|
||||
top={{ sm: '0', md: 'unset' }}
|
||||
left={{ sm: '0', md: 'unset' }}
|
||||
width={{ sm: isOpen ? 'viewWidth' : 'auto', md: 'auto' }}
|
||||
position={{ sm: isOpen ? 'absolute' : 'relative', lg: 'relative' }}
|
||||
top={{ sm: '0', lg: 'unset' }}
|
||||
left={{ sm: '0', lg: 'unset' }}
|
||||
width={{ sm: isOpen ? 'viewWidth' : 'auto', lg: 'auto' }}
|
||||
ref={searchRef}
|
||||
style={{ zIndex: '1000' }}
|
||||
>
|
||||
@ -335,16 +331,16 @@ export const SearchBar = () => {
|
||||
borderRadius={isOpen ? undefined : '12'}
|
||||
borderTopRightRadius={isOpen && !isMobile ? '12' : undefined}
|
||||
borderTopLeftRadius={isOpen && !isMobile ? '12' : undefined}
|
||||
display={{ sm: isOpen ? 'flex' : 'none', md: 'flex' }}
|
||||
display={{ sm: isOpen ? 'flex' : 'none', lg: 'flex' }}
|
||||
justifyContent={isOpen || phase1Flag === NftVariant.Enabled ? 'flex-start' : 'center'}
|
||||
onFocus={() => !isOpen && toggleOpen()}
|
||||
onClick={() => !isOpen && toggleOpen()}
|
||||
gap="12"
|
||||
>
|
||||
<Box display={{ sm: 'none', md: 'flex' }}>
|
||||
<Box display={{ sm: 'none', lg: 'flex' }}>
|
||||
<MagnifyingGlassIcon />
|
||||
</Box>
|
||||
<Box display={{ sm: 'flex', md: 'none' }} color="placeholder" onClick={toggleOpen}>
|
||||
<Box display={{ sm: 'flex', lg: 'none' }} color="placeholder" onClick={toggleOpen}>
|
||||
<ChevronLeftIcon />
|
||||
</Box>
|
||||
<Box
|
||||
@ -359,7 +355,7 @@ export const SearchBar = () => {
|
||||
value={searchValue}
|
||||
/>
|
||||
</Row>
|
||||
<Box display={{ sm: isOpen ? 'none' : 'flex', md: 'none' }}>
|
||||
<Box display={{ sm: isOpen ? 'none' : 'flex', lg: 'none' }}>
|
||||
<NavIcon onClick={toggleOpen}>
|
||||
<NavMagnifyingGlassIcon width={28} height={28} />
|
||||
</NavIcon>
|
||||
|
@ -20,6 +20,10 @@ const WalletWrapper = styled.div`
|
||||
border: ${({ theme }) => `1px solid ${theme.backgroundOutline}`};
|
||||
box-shadow: ${({ theme }) => theme.deepShadow};
|
||||
padding: 16px 0;
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
|
||||
width: 100%;
|
||||
}
|
||||
`
|
||||
|
||||
export enum MenuState {
|
||||
@ -33,11 +37,12 @@ const WalletDropdownWrapper = styled.div`
|
||||
top: 65px;
|
||||
right: 20px;
|
||||
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.xl}px`}) {
|
||||
@media only screen and (max-width: ${({ theme }) => `${theme.breakpoint.sm}px`}) {
|
||||
top: unset;
|
||||
right: 50%;
|
||||
bottom: 45px;
|
||||
transform: translateX(50%);
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 56px;
|
||||
z-index: 1;
|
||||
}
|
||||
`
|
||||
|
||||
|
@ -6,6 +6,8 @@ import { TraceEvent } from 'components/AmplitudeAnalytics/TraceEvent'
|
||||
import WalletDropdown from 'components/WalletDropdown'
|
||||
import { getConnection } from 'connection/utils'
|
||||
import { NavBarVariant, useNavBarFlag } from 'featureFlags/flags/navBar'
|
||||
import { Portal } from 'nft/components/common/Portal'
|
||||
import { useIsMobile } from 'nft/hooks'
|
||||
import { getIsValidSwapQuote } from 'pages/Swap'
|
||||
import { darken } from 'polished'
|
||||
import { useMemo, useRef } from 'react'
|
||||
@ -285,6 +287,7 @@ export default function Web3Status() {
|
||||
const ref = useRef<HTMLDivElement>(null)
|
||||
const closeModal = useCloseModal(ApplicationModal.WALLET_DROPDOWN)
|
||||
const isOpen = useIsOpen()
|
||||
const isMobile = useIsMobile()
|
||||
|
||||
useOnClickOutside(ref, isOpen ? closeModal : undefined)
|
||||
|
||||
@ -300,7 +303,13 @@ export default function Web3Status() {
|
||||
<span ref={ref}>
|
||||
<Web3StatusInner />
|
||||
<WalletModal ENSName={ENSName ?? undefined} pendingTransactions={pending} confirmedTransactions={confirmed} />
|
||||
<WalletDropdown />
|
||||
{isMobile ? (
|
||||
<Portal>
|
||||
<WalletDropdown />
|
||||
</Portal>
|
||||
) : (
|
||||
<WalletDropdown />
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user