|
1 |
| -import { useRef } from "react" |
2 |
| -import { useRouter } from "next/router" |
| 1 | +import { lazy, Suspense, useRef } from "react" |
3 | 2 | import { useTranslation } from "next-i18next"
|
4 |
| -import { BsTranslate } from "react-icons/bs" |
5 |
| -import { MdBrightness2, MdWbSunny } from "react-icons/md" |
6 |
| -import { |
7 |
| - Box, |
8 |
| - Button, |
9 |
| - Flex, |
10 |
| - HStack, |
11 |
| - Icon, |
12 |
| - MenuButton, |
13 |
| - Text, |
14 |
| - useColorModeValue, |
15 |
| - useDisclosure, |
16 |
| - useEventListener, |
17 |
| -} from "@chakra-ui/react" |
| 3 | +import { Box, Flex, Hide, Show, useDisclosure } from "@chakra-ui/react" |
18 | 4 |
|
19 |
| -import { IconButton } from "@/components/Buttons" |
20 | 5 | import { EthHomeIcon } from "@/components/icons"
|
21 |
| -import LanguagePicker from "@/components/LanguagePicker" |
22 | 6 | import { BaseLink } from "@/components/Link"
|
23 | 7 | import Search from "@/components/Search"
|
24 | 8 |
|
25 | 9 | import { isMobile } from "@/lib/utils/isMobile"
|
26 | 10 |
|
27 |
| -import { DESKTOP_LANGUAGE_BUTTON_NAME, NAV_PY } from "@/lib/constants" |
| 11 | +import { NAV_PY } from "@/lib/constants" |
28 | 12 |
|
| 13 | +import DesktopNavMenu from "./Desktop" |
29 | 14 | import Menu from "./Menu"
|
30 |
| -import MobileNavMenu from "./Mobile" |
31 | 15 | import { useNav } from "./useNav"
|
32 | 16 |
|
| 17 | +const MobileNavMenu = lazy(() => import("./Mobile")) |
| 18 | + |
33 | 19 | // TODO display page title on mobile
|
34 | 20 | const Nav = () => {
|
35 | 21 | const { toggleColorMode, linkSections, mobileNavProps } = useNav()
|
36 |
| - const { locale } = useRouter() |
37 | 22 | const { t } = useTranslation("common")
|
38 | 23 | const isDesktop = !isMobile()
|
39 | 24 | const searchModalDisclosure = useDisclosure()
|
40 | 25 | const navWrapperRef = useRef(null)
|
41 |
| - const languagePickerState = useDisclosure() |
42 |
| - const languagePickerRef = useRef<HTMLButtonElement>(null) |
43 |
| - |
44 |
| - /** |
45 |
| - * Adds a keydown event listener to toggle color mode (ctrl|cmd + \) |
46 |
| - * or open the language picker (\). |
47 |
| - * @param {string} event - The keydown event. |
48 |
| - */ |
49 |
| - useEventListener("keydown", (e) => { |
50 |
| - if (e.key !== "\\") return |
51 |
| - e.preventDefault() |
52 |
| - if (e.metaKey || e.ctrlKey) { |
53 |
| - toggleColorMode() |
54 |
| - } else { |
55 |
| - if (languagePickerState.isOpen) return |
56 |
| - languagePickerRef.current?.click() |
57 |
| - } |
58 |
| - }) |
59 |
| - |
60 |
| - const ThemeIcon = useColorModeValue(<MdBrightness2 />, <MdWbSunny />) |
61 |
| - const themeIconAriaLabel = useColorModeValue( |
62 |
| - "Switch to Dark Theme", |
63 |
| - "Switch to Light Theme" |
64 |
| - ) |
65 | 26 |
|
66 | 27 | return (
|
67 | 28 | <Box position="sticky" top={0} zIndex="sticky" width="full">
|
@@ -102,83 +63,26 @@ const Nav = () => {
|
102 | 63 | {isDesktop && <Menu hideBelow="md" sections={linkSections} />}
|
103 | 64 |
|
104 | 65 | <Flex alignItems="center" /* justifyContent="space-between" */>
|
105 |
| - <Search {...searchModalDisclosure} /> |
106 | 66 | {/* Desktop */}
|
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} |
114 |
| - variant="ghost" |
115 |
| - isSecondary |
116 |
| - px={{ base: "2", xl: "3" }} |
117 |
| - _hover={{ |
118 |
| - transform: "rotate(10deg)", |
119 |
| - color: "primary.hover", |
120 |
| - }} |
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} |
133 |
| - > |
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")} |
168 |
| - </Text> |
169 |
| - {locale!.toUpperCase()} |
170 |
| - </MenuButton> |
171 |
| - </LanguagePicker> |
172 |
| - </HStack> |
173 |
| - )} |
| 67 | + {/* avoid rendering desktop menu version on mobile */} |
| 68 | + <Show above="md"> |
| 69 | + <Search {...searchModalDisclosure} /> |
| 70 | + <DesktopNavMenu toggleColorMode={toggleColorMode} /> |
| 71 | + </Show> |
174 | 72 |
|
175 |
| - <MobileNavMenu |
176 |
| - {...mobileNavProps} |
177 |
| - linkSections={linkSections} |
178 |
| - hideFrom="md" |
179 |
| - toggleSearch={searchModalDisclosure.onOpen} |
180 |
| - drawerContainerRef={navWrapperRef} |
181 |
| - /> |
| 73 | + <Hide above="md"> |
| 74 | + {/* Mobile */} |
| 75 | + {/* use Suspense to display the Search & the Menu at the same time */} |
| 76 | + <Suspense> |
| 77 | + <Search {...searchModalDisclosure} /> |
| 78 | + <MobileNavMenu |
| 79 | + {...mobileNavProps} |
| 80 | + linkSections={linkSections} |
| 81 | + toggleSearch={searchModalDisclosure.onOpen} |
| 82 | + drawerContainerRef={navWrapperRef} |
| 83 | + /> |
| 84 | + </Suspense> |
| 85 | + </Hide> |
182 | 86 | </Flex>
|
183 | 87 | </Flex>
|
184 | 88 | </Flex>
|
|
0 commit comments