Skip to content

Commit 3552270

Browse files
author
Google
committed
fix: refactor Topnav
1 parent a3e9466 commit 3552270

File tree

8 files changed

+169
-102
lines changed

8 files changed

+169
-102
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import {Seo} from 'components/Seo';
2+
import SocialBanner from '../SocialBanner';
3+
4+
interface HeaderProps {
5+
title: string;
6+
titleForTitleTag: string;
7+
section: string;
8+
routeTree: any;
9+
breadcrumbs: any;
10+
isHomePage: boolean;
11+
searchOrder: number | undefined;
12+
}
13+
14+
const HeaderComponent = ({
15+
title,
16+
titleForTitleTag,
17+
section,
18+
isHomePage,
19+
searchOrder,
20+
}: HeaderProps) => {
21+
return (
22+
<>
23+
<Seo
24+
title={title}
25+
titleForTitleTag={titleForTitleTag}
26+
isHomePage={isHomePage}
27+
image={`/images/og-` + section + '.png'}
28+
searchOrder={searchOrder}
29+
/>
30+
<SocialBanner />
31+
{/* <TopNav section={section} routeTree={routeTree} breadcrumbs={breadcrumbs} /> */}
32+
</>
33+
);
34+
};
35+
export default HeaderComponent;

src/components/Layout/TopNav/TopNav.tsx

Lines changed: 16 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -2,30 +2,23 @@
22
* Copyright (c) Facebook, Inc. and its affiliates.
33
*/
44

5-
import {
6-
useState,
7-
useRef,
8-
useCallback,
9-
useEffect,
10-
startTransition,
11-
Suspense,
12-
} from 'react';
13-
import Image from 'next/image';
14-
import * as React from 'react';
155
import cn from 'classnames';
6+
import Image from 'next/image';
167
import NextLink from 'next/link';
17-
import {useRouter} from 'next/router';
18-
import {disableBodyScroll, enableBodyScroll} from 'body-scroll-lock';
8+
import * as React from 'react';
9+
import {Suspense} from 'react';
1910

2011
import {IconClose} from 'components/Icon/IconClose';
2112
import {IconHamburger} from 'components/Icon/IconHamburger';
2213
import {IconSearch} from 'components/Icon/IconSearch';
14+
import NavItem from 'components/NavItem';
2315
import {Search} from 'components/Search';
16+
import {useMenuAndScroll} from 'hooks';
17+
import {siteConfig} from 'siteConfig';
2418
import {Logo} from '../../Logo';
2519
import {Feedback} from '../Feedback';
2620
import {SidebarRouteTree} from '../Sidebar';
2721
import type {RouteItem} from '../getRouteMeta';
28-
import {siteConfig} from 'siteConfig';
2922
import BrandMenu from './BrandMenu';
3023

3124
declare global {
@@ -120,23 +113,6 @@ function Link({
120113
);
121114
}
122115

123-
function NavItem({url, isActive, children}: any) {
124-
return (
125-
<div className="flex flex-auto sm:flex-1">
126-
<Link
127-
href={url}
128-
className={cn(
129-
'active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap',
130-
!isActive && 'hover:bg-primary/5 hover:dark:bg-primary-dark/5',
131-
isActive &&
132-
'bg-highlight dark:bg-highlight-dark text-link dark:text-link-dark'
133-
)}>
134-
{children}
135-
</Link>
136-
</div>
137-
);
138-
}
139-
140116
function Kbd(props: {children?: React.ReactNode; wide?: boolean}) {
141117
const {wide, ...rest} = props;
142118
const width = wide ? 'w-10' : 'w-5';
@@ -158,77 +134,16 @@ export default function TopNav({
158134
breadcrumbs: RouteItem[];
159135
section: 'learn' | 'reference' | 'community' | 'blog' | 'home' | 'unknown';
160136
}) {
161-
const [isMenuOpen, setIsMenuOpen] = useState(false);
162-
const [showSearch, setShowSearch] = useState(false);
163-
const [isScrolled, setIsScrolled] = useState(false);
164-
const scrollParentRef = useRef<HTMLDivElement>(null);
165-
const {asPath} = useRouter();
166-
167-
// HACK. Fix up the data structures instead.
168-
if ((routeTree as any).routes.length === 1) {
169-
routeTree = (routeTree as any).routes[0];
170-
}
171-
172-
// While the overlay is open, disable body scroll.
173-
useEffect(() => {
174-
if (isMenuOpen) {
175-
const preferredScrollParent = scrollParentRef.current!;
176-
disableBodyScroll(preferredScrollParent);
177-
return () => enableBodyScroll(preferredScrollParent);
178-
} else {
179-
return undefined;
180-
}
181-
}, [isMenuOpen]);
182-
183-
// Close the overlay on any navigation.
184-
useEffect(() => {
185-
setIsMenuOpen(false);
186-
}, [asPath]);
187-
188-
// Also close the overlay if the window gets resized past mobile layout.
189-
// (This is also important because we don't want to keep the body locked!)
190-
useEffect(() => {
191-
const media = window.matchMedia(`(max-width: 1023px)`);
192-
193-
function closeIfNeeded() {
194-
if (!media.matches) {
195-
setIsMenuOpen(false);
196-
}
197-
}
198-
199-
closeIfNeeded();
200-
media.addEventListener('change', closeIfNeeded);
201-
return () => {
202-
media.removeEventListener('change', closeIfNeeded);
203-
};
204-
}, []);
205-
206-
const scrollDetectorRef = useRef(null);
207-
useEffect(() => {
208-
const observer = new IntersectionObserver(
209-
(entries) => {
210-
entries.forEach((entry) => {
211-
setIsScrolled(!entry.isIntersecting);
212-
});
213-
},
214-
{
215-
root: null,
216-
rootMargin: `0px 0px`,
217-
threshold: 0,
218-
}
219-
);
220-
observer.observe(scrollDetectorRef.current!);
221-
return () => observer.disconnect();
222-
}, []);
223-
224-
const onOpenSearch = useCallback(() => {
225-
startTransition(() => {
226-
setShowSearch(true);
227-
});
228-
}, []);
229-
const onCloseSearch = useCallback(() => {
230-
setShowSearch(false);
231-
}, []);
137+
const {
138+
isMenuOpen,
139+
setIsMenuOpen,
140+
showSearch,
141+
isScrolled,
142+
scrollParentRef,
143+
scrollDetectorRef,
144+
onOpenSearch,
145+
onCloseSearch,
146+
} = useMenuAndScroll(routeTree);
232147

233148
return (
234149
<>

src/components/NavItem/index.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Link from 'next/link';
2+
import cn from 'classnames';
3+
4+
const NavItem = ({url, isActive, children}: any) => {
5+
return (
6+
<div className="flex flex-auto sm:flex-1">
7+
<Link
8+
href={url}
9+
className={cn(
10+
'active:scale-95 transition-transform w-full text-center outline-link py-1.5 px-1.5 xs:px-3 sm:px-4 rounded-full capitalize whitespace-nowrap',
11+
!isActive && 'hover:bg-primary/5 hover:dark:bg-primary-dark/5',
12+
isActive &&
13+
'bg-highlight dark:bg-highlight-dark text-link dark:text-link-dark'
14+
)}>
15+
{children}
16+
</Link>
17+
</div>
18+
);
19+
};
20+
export default NavItem;

src/components/PageHeading.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ function PageHeading({
2727
tags = [],
2828
breadcrumbs,
2929
}: PageHeadingProps) {
30-
console.log('version', version);
3130
return (
3231
<div className="px-5 sm:px-12 pt-3.5">
3332
<div className="max-w-4xl ms-0 2xl:mx-auto">

src/components/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export {default as HeaderComponent} from './HeaderComponent';
2+
export {default as NavItem} from './NavItem';

src/content/learn/passing-data-deeply-with-context.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -583,6 +583,14 @@ export default function Page() {
583583
...
584584
<Section level={3}>
585585
...
586+
<Section level={4}>
587+
...
588+
</Section>
589+
</Section>
590+
</Section>
591+
</Section>
592+
);
593+
}
586594
```
587595

588596
Since context lets you read information from a component above, each `Section` could read the `level` from the `Section` above, and pass `level + 1` down automatically. Here is how you could do it:

src/hooks/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export {default as useMenuAndScroll} from './useMenuAndScroll';

src/hooks/useMenuAndScroll.ts

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import {useState, useEffect, useRef, useCallback, startTransition} from 'react';
2+
import {useRouter} from 'next/router';
3+
import {disableBodyScroll, enableBodyScroll} from 'body-scroll-lock';
4+
import {RouteItem} from 'components/Layout/getRouteMeta';
5+
6+
const useMenuAndScroll = (routeTree: RouteItem) => {
7+
const [isMenuOpen, setIsMenuOpen] = useState(false);
8+
const [showSearch, setShowSearch] = useState(false);
9+
const [isScrolled, setIsScrolled] = useState(false);
10+
const scrollParentRef = useRef<HTMLDivElement>(null);
11+
const {asPath} = useRouter();
12+
const scrollDetectorRef = useRef(null);
13+
14+
if ((routeTree as any).routes.length === 1) {
15+
routeTree = (routeTree as any).routes[0];
16+
}
17+
18+
useEffect(() => {
19+
if (isMenuOpen) {
20+
const preferredScrollParent = scrollParentRef.current!;
21+
disableBodyScroll(preferredScrollParent);
22+
return () => enableBodyScroll(preferredScrollParent);
23+
} else {
24+
return undefined;
25+
}
26+
}, [isMenuOpen]);
27+
28+
useEffect(() => {
29+
setIsMenuOpen(false);
30+
}, [asPath]);
31+
32+
useEffect(() => {
33+
const media = window.matchMedia(`(max-width: 1023px)`);
34+
35+
function closeIfNeeded() {
36+
if (!media.matches) {
37+
setIsMenuOpen(false);
38+
}
39+
}
40+
41+
closeIfNeeded();
42+
media.addEventListener('change', closeIfNeeded);
43+
return () => {
44+
media.removeEventListener('change', closeIfNeeded);
45+
};
46+
}, []);
47+
48+
useEffect(() => {
49+
const observer = new IntersectionObserver(
50+
(entries) => {
51+
entries.forEach((entry) => {
52+
setIsScrolled(!entry.isIntersecting);
53+
});
54+
},
55+
{
56+
root: null,
57+
rootMargin: `0px 0px`,
58+
threshold: 0,
59+
}
60+
);
61+
observer.observe(scrollDetectorRef.current!);
62+
return () => observer.disconnect();
63+
}, []);
64+
65+
const onOpenSearch = useCallback(() => {
66+
startTransition(() => {
67+
setShowSearch(true);
68+
});
69+
}, []);
70+
71+
const onCloseSearch = useCallback(() => {
72+
setShowSearch(false);
73+
}, []);
74+
75+
return {
76+
isMenuOpen,
77+
setIsMenuOpen,
78+
showSearch,
79+
setShowSearch,
80+
isScrolled,
81+
scrollParentRef,
82+
scrollDetectorRef,
83+
onOpenSearch,
84+
onCloseSearch,
85+
};
86+
};
87+
export default useMenuAndScroll;

0 commit comments

Comments
 (0)