Skip to content

Commit

Permalink
perf: improve rendering performance of mobile sidebar (#5471)
Browse files Browse the repository at this point in the history
  • Loading branch information
woodenfurniture authored Oct 17, 2023
1 parent fdb68f9 commit 19b4b9a
Show file tree
Hide file tree
Showing 16 changed files with 255 additions and 152 deletions.
14 changes: 7 additions & 7 deletions src/components/Banners/YatBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { LinkProps } from '@chakra-ui/react'
import { Flex, Link, Tooltip, useMediaQuery } from '@chakra-ui/react'
import { ethChainId, fromAccountId } from '@shapeshiftoss/caip'
import { useMemo } from 'react'
import { memo, useMemo } from 'react'
import { useTranslate } from 'react-polyglot'
import { YatIcon } from 'components/Icons/YatIcon'
import { Text } from 'components/Text'
Expand All @@ -14,7 +14,9 @@ type YatBannerProps = {
isCompact?: boolean
} & LinkProps

export const YatBanner: React.FC<YatBannerProps> = ({ isCompact, ...rest }) => {
const hoverProp = { boxShadow: '0 0 0 2px var(--chakra-colors-chakra-body-text) inset' }

export const YatBanner: React.FC<YatBannerProps> = memo(({ isCompact, ...rest }) => {
const [isLargerThan2xl] = useMediaQuery(`(min-width: ${breakpoints['2xl']})`, { ssr: false })
const translate = useTranslate()
const { isDemoWallet } = useWallet().state
Expand Down Expand Up @@ -52,11 +54,9 @@ export const YatBanner: React.FC<YatBannerProps> = ({ isCompact, ...rest }) => {
isExternal
display='block'
aria-label={translate('features.yat.banner.title')}
_hover={{ boxShadow: '0 0 0 2px var(--chakra-colors-chakra-body-text) inset' }}
_hover={hoverProp}
borderRadius='xl'
backgroundImage={
'radial-gradient(circle at bottom left, #00C1C165 0%, transparent 30%), radial-gradient(circle at top right, #7B61FF70 0%, transparent 50%)'
}
backgroundImage='radial-gradient(circle at bottom left, #00C1C165 0%, transparent 30%), radial-gradient(circle at top right, #7B61FF70 0%, transparent 50%)'
{...rest}
>
<Flex
Expand All @@ -83,4 +83,4 @@ export const YatBanner: React.FC<YatBannerProps> = ({ isCompact, ...rest }) => {
</Link>
</Tooltip>
)
}
})
7 changes: 4 additions & 3 deletions src/components/Layout/Header/AppLoadingIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import { Center } from '@chakra-ui/react'
import { AnimatePresence } from 'framer-motion'
import { memo } from 'react'
import { Link } from 'react-router-dom'
import { CircularProgress } from 'components/CircularProgress/CircularProgress'
import { FoxIcon } from 'components/Icons/FoxIcon'
import { SlideTransitionY } from 'components/SlideTransitionY'
import { useIsAnyApiFetching } from 'hooks/useIsAnyApiFetching/useIsAnyApiFetching'

export const AppLoadingIcon: React.FC = () => {
export const AppLoadingIcon: React.FC = memo(() => {
const isLoading = useIsAnyApiFetching()
return (
<Link to='/'>
<AnimatePresence exitBeforeEnter initial={true}>
<AnimatePresence exitBeforeEnter initial>
{isLoading ? (
<SlideTransitionY key='loader'>
<Center boxSize='7'>
Expand All @@ -25,4 +26,4 @@ export const AppLoadingIcon: React.FC = () => {
</AnimatePresence>
</Link>
)
}
})
6 changes: 3 additions & 3 deletions src/components/Layout/Header/DegradedStateBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
} from '@chakra-ui/react'
import type { AccountId } from '@shapeshiftoss/caip'
import { entries, isEmpty, uniq } from 'lodash'
import { useCallback, useMemo } from 'react'
import { memo, useCallback, useMemo } from 'react'
import { IoMdRefresh } from 'react-icons/io'
import { useTranslate } from 'react-polyglot'
import { useSelector } from 'react-redux'
Expand All @@ -26,7 +26,7 @@ import { accountIdToFeeAssetId } from 'state/slices/portfolioSlice/utils'
import { selectAssets, selectPortfolioLoadingStatusGranular } from 'state/slices/selectors'
import { useAppDispatch } from 'state/store'

export const DegradedStateBanner = () => {
export const DegradedStateBanner = memo(() => {
const dispatch = useAppDispatch()
const translate = useTranslate()
const footerBg = useColorModeValue('blackAlpha.100', 'whiteAlpha.100')
Expand Down Expand Up @@ -131,4 +131,4 @@ export const DegradedStateBanner = () => {
</PopoverContent>
</Popover>
)
}
})
26 changes: 17 additions & 9 deletions src/components/Layout/Header/GlobalSearch/GlobalSearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
import { fromAssetId } from '@shapeshiftoss/caip'
import { isEvmChainId } from '@shapeshiftoss/chain-adapters'
import { DefiAction } from 'features/defi/contexts/DefiManagerProvider/DefiCommon'
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import MultiRef from 'react-multi-ref'
import { useTranslate } from 'react-polyglot'
import { generatePath, useHistory, useLocation } from 'react-router'
Expand Down Expand Up @@ -48,7 +48,15 @@ import { StakingResults } from './StakingResults/StakingResults'
import { TxResults } from './TxResults/TxResults'
import { makeOpportunityRouteDetails } from './utils'

export const GlobalSeachButton = () => {
const mrProp = { base: 0, md: 'auto' }
const widthProp = { base: 'auto', md: 'full' }
const displayProp1 = { base: 'flex', md: 'none' }
const displayProp2 = { base: 'none', md: 'flex' }
const inputGroupProps = { size: 'xl' }
const sxProp1 = { svg: { width: '18px', height: '18px' } }
const sxProp2 = { p: 0 }

export const GlobalSeachButton = memo(() => {
const { isOpen, onClose, onOpen, onToggle } = useDisclosure()
const [sendResults, setSendResults] = useState<SendResult[]>([])
const [activeIndex, setActiveIndex] = useState(0)
Expand Down Expand Up @@ -301,9 +309,9 @@ export const GlobalSeachButton = () => {

return (
<>
<Box maxWidth='xl' width={{ base: 'auto', md: 'full' }} mr={{ base: 0, md: 'auto' }}>
<Box maxWidth='xl' width={widthProp} mr={mrProp}>
<IconButton
display={{ base: 'flex', md: 'none' }}
display={displayProp1}
icon={<SearchIcon />}
aria-label='Search'
onClick={onOpen}
Expand All @@ -316,8 +324,8 @@ export const GlobalSeachButton = () => {
fontSize='md'
alignItems='center'
color='text.subtle'
display={{ base: 'none', md: 'flex' }}
sx={{ svg: { width: '18px', height: '18px' } }}
display={displayProp2}
sx={sxProp1}
>
{translate('common.search')}
{!isMobileApp && ( // Mobile app users are unlikely to have access to a keyboard for the shortcut.
Expand All @@ -333,15 +341,15 @@ export const GlobalSeachButton = () => {
<ModalHeader
position='sticky'
top={0}
sx={{ p: 0 }}
sx={sxProp2}
borderBottomWidth={1}
borderColor='whiteAlpha.100'
>
<GlobalFilter
searchQuery={searchQuery}
setSearchQuery={setSearchQuery}
onKeyDown={onKeyDown}
inputGroupProps={{ size: 'xl' }}
inputGroupProps={inputGroupProps}
borderBottomRadius={0}
borderWidth={0}
/>
Expand All @@ -353,4 +361,4 @@ export const GlobalSeachButton = () => {
</Modal>
</>
)
}
})
48 changes: 33 additions & 15 deletions src/components/Layout/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
HStack,
IconButton,
useDisclosure,
useMediaQuery,
usePrevious,
useToast,
} from '@chakra-ui/react'
Expand All @@ -34,6 +35,7 @@ import {
selectWalletId,
} from 'state/slices/selectors'
import { useAppDispatch } from 'state/store'
import { breakpoints } from 'theme/theme'

import { AppLoadingIcon } from './AppLoadingIcon'
import { DegradedStateBanner } from './DegradedStateBanner'
Expand All @@ -45,13 +47,22 @@ import { UserMenu } from './NavBar/UserMenu'
import { SideNavContent } from './SideNavContent'
import { TxWindow } from './TxWindow/TxWindow'

const paddingBottomProp = { base: '0.5rem', md: 0 }
const fontSizeProp = { base: 'sm', md: 'md' }
const paddingTopProp1 = { base: 'calc(0.5rem + env(safe-area-inset-top))', md: 0 }
const pxProp = { base: 0, xl: 4 }
const displayProp = { base: 'block', md: 'none' }
const displayProp2 = { base: 'none', md: 'block' }
const widthProp = { base: 'auto', md: 'full' }

export const Header = memo(() => {
const { onToggle, isOpen, onClose } = useDisclosure()
const isDegradedState = useSelector(selectPortfolioLoadingStatus) === 'error'
const snapModal = useModal('snaps')
const isSnapInstalled = useIsSnapInstalled()
const previousSnapInstall = usePrevious(isSnapInstalled)
const showSnapModal = useSelector(selectShowSnapsModal)
const [isLargerThanMd] = useMediaQuery(`(min-width: ${breakpoints['md']})`, { ssr: false })

const history = useHistory()
const {
Expand Down Expand Up @@ -149,16 +160,21 @@ export const Header = memo(() => {
walletAccountIds,
])

const paddingTopProp2 = useMemo(
() => ({ base: isDemoWallet ? 0 : 'env(safe-area-inset-top)', md: 0 }),
[isDemoWallet],
)

return (
<>
{isDemoWallet && (
<Box
bg='blue.500'
width='full'
paddingTop={{ base: 'calc(0.5rem + env(safe-area-inset-top))', md: 0 }}
paddingBottom={{ base: '0.5rem', md: 0 }}
paddingTop={paddingTopProp1}
paddingBottom={paddingBottomProp}
minHeight='2.5rem'
fontSize={{ base: 'sm', md: 'md' }}
fontSize={fontSizeProp}
as='button'
onClick={handleBannerClick}
>
Expand Down Expand Up @@ -186,39 +202,41 @@ export const Header = memo(() => {
transitionProperty='all'
transitionTimingFunction='cubic-bezier(0.4, 0, 0.2, 1)'
top={0}
paddingTop={{ base: isDemoWallet ? 0 : 'env(safe-area-inset-top)', md: 0 }}
paddingTop={paddingTopProp2}
>
<HStack height='4.5rem' width='full' px={4}>
<HStack width='full' margin='0 auto' px={{ base: 0, xl: 4 }} spacing={0} columnGap={4}>
<Box flex={1} display={{ base: 'block', md: 'none' }}>
<HStack width='full' margin='0 auto' px={pxProp} spacing={0} columnGap={4}>
<Box flex={1} display={displayProp}>
<IconButton aria-label='Open menu' onClick={onToggle} icon={<HamburgerIcon />} />
</Box>

<Box display={{ base: 'block', md: 'none' }} mx='auto'>
<Box display={displayProp} mx='auto'>
<AppLoadingIcon />
</Box>

<Flex
justifyContent='flex-end'
alignItems='center'
width={{ base: 'auto', md: 'full' }}
width={widthProp}
flex={1}
rowGap={4}
columnGap={2}
>
<GlobalSeachButton />
{isDegradedState && <DegradedStateBanner />}
{isWalletConnectToDappsV2Enabled && (
<Box display={{ base: 'none', md: 'block' }}>
{isLargerThanMd && isDegradedState && <DegradedStateBanner />}
{isLargerThanMd && isWalletConnectToDappsV2Enabled && (
<Box display={displayProp2}>
<WalletConnectToDappsHeaderButton />
</Box>
)}
<ChainMenu display={{ base: 'none', md: 'block' }} />
{isLargerThanMd && <ChainMenu display={displayProp2} />}
<TxWindow />
<Notifications />
<Box display={{ base: 'none', md: 'block' }}>
<UserMenu />
</Box>
{isLargerThanMd && (
<Box display={displayProp2}>
<UserMenu />
</Box>
)}
</Flex>
</HStack>
</HStack>
Expand Down
15 changes: 10 additions & 5 deletions src/components/Layout/Header/NavBar/ChainMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { EvmBaseAdapter, EvmChainId } from '@shapeshiftoss/chain-adapters'
import type { ETHWallet } from '@shapeshiftoss/hdwallet-core'
import { supportsEthSwitchChain } from '@shapeshiftoss/hdwallet-core'
import { utils } from 'ethers'
import { useCallback, useMemo } from 'react'
import { memo, useCallback, useMemo } from 'react'
import { useTranslate } from 'react-polyglot'
import { AssetIcon } from 'components/AssetIcon'
import { CircleIcon } from 'components/Icons/Circle'
Expand All @@ -42,14 +42,19 @@ const ChainMenuItem: React.FC<{

const connectedIconColor = useColorModeValue('green.500', 'green.200')
const connectedChainBgColor = useColorModeValue('blackAlpha.100', 'whiteAlpha.50')
const assetIcon = useMemo(
() => <AssetIcon assetId={nativeAssetId} showNetworkIcon width='6' height='auto' />,
[nativeAssetId],
)
const handleClick = useCallback(() => onClick(ethNetwork), [ethNetwork, onClick])

if (!nativeAsset) return null

return (
<MenuItem
icon={<AssetIcon assetId={nativeAssetId} showNetworkIcon width='6' height='auto' />}
icon={assetIcon}
backgroundColor={isConnected ? connectedChainBgColor : undefined}
onClick={() => onClick(ethNetwork)}
onClick={handleClick}
borderRadius='lg'
>
<Flex justifyContent={'space-between'}>
Expand All @@ -62,7 +67,7 @@ const ChainMenuItem: React.FC<{

type ChainMenuProps = BoxProps

export const ChainMenu = (props: ChainMenuProps) => {
export const ChainMenu = memo((props: ChainMenuProps) => {
const { state, load } = useWallet()
const {
connectedEvmChainId,
Expand Down Expand Up @@ -177,4 +182,4 @@ export const ChainMenu = (props: ChainMenuProps) => {
</Menu>
</Box>
)
}
})
Loading

0 comments on commit 19b4b9a

Please sign in to comment.