diff --git a/apps/spa/src/components/Navbar.tsx b/apps/spa/src/components/Navbar.tsx index 494f340..ffb2942 100644 --- a/apps/spa/src/components/Navbar.tsx +++ b/apps/spa/src/components/Navbar.tsx @@ -27,6 +27,7 @@ export default function Navbar({ topOffsetClassName = 'top-0', isTransparent = f const [searchQuery, setSearchQuery] = useState('') const [scrolled, setScrolled] = useState(false) const [hasAnnouncement, setHasAnnouncement] = useState(false) + const [isClientReady, setIsClientReady] = useState(false) const [settings, setSettings] = useState(null) const navigate = useNavigate() @@ -55,6 +56,7 @@ export default function Navbar({ topOffsetClassName = 'top-0', isTransparent = f } useEffect(() => { + setIsClientReady(true) fetchMegaMenu() const checkAnnouncement = () => { @@ -173,7 +175,7 @@ export default function Navbar({ topOffsetClassName = 'top-0', isTransparent = f {/* Center: Desktop mega menu */} - {isDesktop && ( + {isClientReady && isDesktop && (
@@ -219,7 +221,7 @@ export default function Navbar({ topOffsetClassName = 'top-0', isTransparent = f )} - {isDesktop && ( + {isClientReady && isDesktop && ( <>
- {!isDesktop && ( + {isClientReady && !isDesktop && mobileOpen && ( setMobileOpen(false)} @@ -345,47 +347,45 @@ export default function Navbar({ topOffsetClassName = 'top-0', isTransparent = f )} -
-
setLangSheetOpen(false)} - /> -
-
-
-
-
-
-

- - Select Language -

- + {langSheetOpen && ( +
+
setLangSheetOpen(false)} + /> +
+
+
-
- {LANGUAGES.map(lang => { - const isActive = i18n.language.startsWith(lang.code) - return ( - - ) - })} +
+
+

+ + Select Language +

+ +
+
+ {LANGUAGES.map(lang => { + const isActive = i18n.language.startsWith(lang.code) + return ( + + ) + })} +
-
+ )} ) } diff --git a/apps/website/src/components/Navbar.tsx b/apps/website/src/components/Navbar.tsx index e49b1e4..21c9346 100644 --- a/apps/website/src/components/Navbar.tsx +++ b/apps/website/src/components/Navbar.tsx @@ -47,6 +47,8 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n const [langSheetOpen, setLangSheetOpen] = useState(false) const [searchQuery, setSearchQuery] = useState('') const [scrolled, setScrolled] = useState(false) + const [isClientReady, setIsClientReady] = useState(false) + const [canRenderDesktopMenu, setCanRenderDesktopMenu] = useState(false) // Seed from server-fetched initialMenu — no client flash const [megaMenu] = useState(initialMenu) const navRef = useRef(null) @@ -153,6 +155,18 @@ export default function Navbar({ categories = [], initialMenu = [], settings = n const isHome = getPathWithoutLocale(pathname) === '/' const isTransparent = isHome && !scrolled && !mobileOpen && !searchOpen && !langSheetOpen + useEffect(() => { + setIsClientReady(true) + + const mediaQuery = window.matchMedia('(min-width: 768px)') + const updateDesktopMenu = () => setCanRenderDesktopMenu(mediaQuery.matches) + + updateDesktopMenu() + mediaQuery.addEventListener('change', updateDesktopMenu) + + return () => mediaQuery.removeEventListener('change', updateDesktopMenu) + }, []) + return ( <> - setMobileOpen(false)} - onOpenLang={() => setLangSheetOpen(true)} - onLogin={loginWithLine} - onLogout={logout} - /> + {isClientReady && mobileOpen && ( + setMobileOpen(false)} + onOpenLang={() => setLangSheetOpen(true)} + onLogin={loginWithLine} + onLogout={logout} + /> + )} {searchOpen && (
)} -
-
setLangSheetOpen(false)} - /> -
-
-
-
-
-
-

- - Select Language -

- + {langSheetOpen && ( +
+
setLangSheetOpen(false)} + /> +
+
+
-
- {LANGUAGES.map((language) => { - const isActive = lang.startsWith(language.code) || language.code.startsWith(lang) - return ( - - ) - })} +
+
+

+ + Select Language +

+ +
+
+ {LANGUAGES.map((language) => { + const isActive = lang.startsWith(language.code) || language.code.startsWith(lang) + return ( + + ) + })} +
-
+ )} ) }