Skip to content

Commit bd0b88d

Browse files
authored
Merge pull request #13042 from ethereum/performance-avoid-desktop-nav-rendering-on-mobile
performance: avoid desktop/mobile menus unnecesary renderings
2 parents 84f6293 + 6421af4 commit bd0b88d

File tree

3 files changed

+121
-95
lines changed

3 files changed

+121
-95
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { MouseEventHandler } from "react"
2+
import { useTranslation } from "next-i18next"
3+
import { Flex } from "@chakra-ui/react"
4+
5+
import { Button } from "@/components/Buttons"
6+
7+
type MobileCloseBarProps = {
8+
handleClick: MouseEventHandler<HTMLButtonElement>
9+
}
10+
11+
export const MobileCloseBar = ({ handleClick }: MobileCloseBarProps) => {
12+
const { t } = useTranslation()
13+
14+
return (
15+
<Flex
16+
justifyContent="end"
17+
hideFrom="md"
18+
position="sticky"
19+
zIndex="sticky"
20+
top="0"
21+
bg="background.base"
22+
>
23+
<Button p="4" variant="ghost" alignSelf="end" onClick={handleClick}>
24+
{t("close")}
25+
</Button>
26+
</Flex>
27+
)
28+
}

src/components/LanguagePicker/index.tsx

Lines changed: 25 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@ import {
1616
useEventListener,
1717
} from "@chakra-ui/react"
1818

19-
import { Button } from "@/components/Buttons"
19+
import { LocaleDisplayInfo } from "@/lib/types"
20+
2021
import { BaseLink } from "@/components/Link"
2122

23+
import { isMobile } from "@/lib/utils/isMobile"
24+
2225
import MenuItem from "./MenuItem"
26+
import { MobileCloseBar } from "./MobileCloseBar"
2327
import NoResultsCallout from "./NoResultsCallout"
2428
import { useLanguagePicker } from "./useLanguagePicker"
2529

@@ -59,6 +63,19 @@ const LanguagePicker = ({
5963
inputRef.current?.focus()
6064
})
6165

66+
// onClick handlers
67+
const handleMobileCloseBarClick = () => onClose()
68+
const handleMenuItemClose = (displayInfo: LocaleDisplayInfo) =>
69+
onClose({
70+
eventAction: "Locale chosen",
71+
eventName: displayInfo.localeOption,
72+
})
73+
const handleBaseLinkClose = () =>
74+
onClose({
75+
eventAction: "Translation program link (menu footer)",
76+
eventName: "/contributing/translation-program",
77+
})
78+
6279
return (
6380
<Menu isLazy placement={placement} autoSelect={false} {...disclosure}>
6481
{children}
@@ -76,23 +93,10 @@ const LanguagePicker = ({
7693
{...props}
7794
>
7895
{/* Mobile Close bar */}
79-
<Flex
80-
justifyContent="end"
81-
hideFrom="md"
82-
position="sticky"
83-
zIndex="sticky"
84-
top="0"
85-
bg="background.base"
86-
>
87-
<Button
88-
p="4"
89-
variant="ghost"
90-
alignSelf="end"
91-
onClick={() => onClose()}
92-
>
93-
{t("common:close")}
94-
</Button>
95-
</Flex>
96+
{/* avoid rendering mobile only feature on desktop */}
97+
{isMobile() && (
98+
<MobileCloseBar handleClick={handleMobileCloseBarClick} />
99+
)}
96100

97101
{/* Main Language selection menu */}
98102
<Box
@@ -146,10 +150,7 @@ const LanguagePicker = ({
146150
}}
147151
onFocus={handleInputFocus}
148152
/>
149-
<InputRightElement
150-
hideBelow="md"
151-
cursor="text"
152-
>
153+
<InputRightElement hideBelow="md" cursor="text">
153154
<Kbd
154155
fontSize="sm"
155156
lineHeight="none"
@@ -177,12 +178,7 @@ const LanguagePicker = ({
177178
e.preventDefault()
178179
inputRef.current?.focus()
179180
}}
180-
onClick={() =>
181-
onClose({
182-
eventAction: "Locale chosen",
183-
eventName: displayInfo.localeOption,
184-
})
185-
}
181+
onClick={() => handleMenuItemClose(displayInfo)}
186182
/>
187183
))}
188184

@@ -215,12 +211,7 @@ const LanguagePicker = ({
215211
<BaseLink
216212
ref={footerRef}
217213
href="/contributing/translation-program"
218-
onClick={() =>
219-
onClose({
220-
eventAction: "Translation program link (menu footer)",
221-
eventName: "/contributing/translation-program",
222-
})
223-
}
214+
onClick={handleBaseLinkClose}
224215
>
225216
{t("common:learn-more")}
226217
</BaseLink>

src/components/Nav/index.tsx

Lines changed: 68 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ import LanguagePicker from "@/components/LanguagePicker"
2222
import { BaseLink } from "@/components/Link"
2323
import Search from "@/components/Search"
2424

25+
import { isMobile } from "@/lib/utils/isMobile"
26+
2527
import { DESKTOP_LANGUAGE_BUTTON_NAME, NAV_PY } from "@/lib/constants"
2628

2729
import Menu from "./Menu"
@@ -33,6 +35,7 @@ const Nav = () => {
3335
const { toggleColorMode, linkSections, mobileNavProps } = useNav()
3436
const { locale } = useRouter()
3537
const { t } = useTranslation("common")
38+
const isDesktop = !isMobile()
3639
const searchModalDisclosure = useDisclosure()
3740
const navWrapperRef = useRef(null)
3841
const languagePickerState = useDisclosure()
@@ -95,76 +98,80 @@ const Nav = () => {
9598
justifyContent={{ base: "flex-end", md: "space-between" }}
9699
ms={{ base: 3, xl: 8 }}
97100
>
98-
<Menu hideBelow="md" sections={linkSections} />
101+
{/* avoid rendering desktop Menu version on mobile */}
102+
{isDesktop && <Menu hideBelow="md" sections={linkSections} />}
103+
99104
<Flex alignItems="center" /* justifyContent="space-between" */>
100105
<Search {...searchModalDisclosure} />
101-
102106
{/* Desktop */}
103-
<HStack hideBelow="md" gap="0">
104-
<IconButton
105-
transition="transform 0.5s, color 0.2s"
106-
icon={ThemeIcon}
107-
aria-label={themeIconAriaLabel}
108-
variant="ghost"
109-
isSecondary
110-
px={{ base: "2", xl: "3" }}
111-
_hover={{
112-
transform: "rotate(10deg)",
113-
color: "primary.hover",
114-
}}
115-
onClick={toggleColorMode}
116-
/>
117-
118-
{/* Locale-picker menu */}
119-
<LanguagePicker
120-
placement="bottom-end"
121-
minH="unset"
122-
maxH="75vh"
123-
w="xs"
124-
inset="unset"
125-
top="unset"
126-
menuState={languagePickerState}
127-
>
128-
<MenuButton
129-
as={Button}
130-
name={DESKTOP_LANGUAGE_BUTTON_NAME}
131-
ref={languagePickerRef}
107+
{/* avoid rendering desktop LanguagePicker version on mobile */}
108+
{isDesktop && (
109+
<HStack hideBelow="md" gap="0">
110+
<IconButton
111+
transition="transform 0.5s, color 0.2s"
112+
icon={ThemeIcon}
113+
aria-label={themeIconAriaLabel}
132114
variant="ghost"
133-
color="body.base"
134-
transition="color 0.2s"
115+
isSecondary
135116
px={{ base: "2", xl: "3" }}
136117
_hover={{
118+
transform: "rotate(10deg)",
137119
color: "primary.hover",
138-
"& svg": {
139-
transform: "rotate(10deg)",
140-
transition: "transform 0.5s",
141-
},
142-
}}
143-
_active={{
144-
color: "primary.hover",
145-
bg: "primary.lowContrast",
146-
}}
147-
sx={{
148-
"& svg": {
149-
transform: "rotate(0deg)",
150-
transition: "transform 0.5s",
151-
},
152120
}}
121+
onClick={toggleColorMode}
122+
/>
123+
124+
{/* Locale-picker menu */}
125+
<LanguagePicker
126+
placement="bottom-end"
127+
minH="unset"
128+
maxH="75vh"
129+
w="xs"
130+
inset="unset"
131+
top="unset"
132+
menuState={languagePickerState}
153133
>
154-
<Icon
155-
as={BsTranslate}
156-
fontSize="2xl"
157-
verticalAlign="middle"
158-
me={2}
159-
/>
160-
<Text hideBelow="lg" as="span">
161-
{t("common:languages")}&nbsp;
162-
</Text>
163-
{locale!.toUpperCase()}
164-
</MenuButton>
165-
</LanguagePicker>
166-
</HStack>
167-
{/* Mobile */}
134+
<MenuButton
135+
as={Button}
136+
name={DESKTOP_LANGUAGE_BUTTON_NAME}
137+
ref={languagePickerRef}
138+
variant="ghost"
139+
color="body.base"
140+
transition="color 0.2s"
141+
px={{ base: "2", xl: "3" }}
142+
_hover={{
143+
color: "primary.hover",
144+
"& svg": {
145+
transform: "rotate(10deg)",
146+
transition: "transform 0.5s",
147+
},
148+
}}
149+
_active={{
150+
color: "primary.hover",
151+
bg: "primary.lowContrast",
152+
}}
153+
sx={{
154+
"& svg": {
155+
transform: "rotate(0deg)",
156+
transition: "transform 0.5s",
157+
},
158+
}}
159+
>
160+
<Icon
161+
as={BsTranslate}
162+
fontSize="2xl"
163+
verticalAlign="middle"
164+
me={2}
165+
/>
166+
<Text hideBelow="lg" as="span">
167+
{t("common:languages")}&nbsp;
168+
</Text>
169+
{locale!.toUpperCase()}
170+
</MenuButton>
171+
</LanguagePicker>
172+
</HStack>
173+
)}
174+
168175
<MobileNavMenu
169176
{...mobileNavProps}
170177
linkSections={linkSections}

0 commit comments

Comments
 (0)