Skip to content

Commit af27aba

Browse files
committed
v1
1 parent 521052d commit af27aba

File tree

13 files changed

+355
-111
lines changed

13 files changed

+355
-111
lines changed

.changeset/sweet-hornets-change.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'gitbook': minor
3+
---
4+
5+
Revamp mobile navigation

bun.lock

Lines changed: 82 additions & 27 deletions
Large diffs are not rendered by default.

packages/gitbook/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"@gitbook/react-math": "workspace:*",
2828
"@gitbook/react-openapi": "workspace:*",
2929
"@radix-ui/react-checkbox": "^1.0.4",
30+
"@radix-ui/react-dialog": "^1.1.14",
3031
"@radix-ui/react-dropdown-menu": "^2.1.12",
3132
"@radix-ui/react-navigation-menu": "^1.2.3",
3233
"@radix-ui/react-popover": "^1.0.7",

packages/gitbook/src/components/Header/Header.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { HeaderLink } from './HeaderLink';
1111
import { HeaderLinkMore } from './HeaderLinkMore';
1212
import { HeaderLinks } from './HeaderLinks';
1313
import { HeaderLogo } from './HeaderLogo';
14-
import { HeaderMobileMenu } from './HeaderMobileMenu';
14+
import { HeaderMobileMenuButton } from './HeaderMobileMenuButton';
1515
import { SpacesDropdown } from './SpacesDropdown';
1616

1717
/**
@@ -76,7 +76,8 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
7676
'min-w-0 shrink items-center justify-start gap-2 lg:gap-4'
7777
)}
7878
>
79-
<HeaderMobileMenu
79+
<HeaderMobileMenuButton
80+
pages={context.pages}
8081
className={tcls(
8182
'lg:hidden',
8283
'-ml-2',

packages/gitbook/src/components/Header/HeaderMobileMenu.tsx renamed to packages/gitbook/src/components/Header/HeaderMobileMenuButton.tsx

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,35 @@
11
'use client';
22

33
import { Icon } from '@gitbook/icons';
4-
import { usePathname } from 'next/navigation';
5-
import { useEffect, useRef } from 'react';
4+
import { useEffect } from 'react';
65

6+
import { useMobileMenuSheet } from '@/components/Header/mobile-menu/useMobileMenuSheet';
77
import { tString, useLanguage } from '@/intl/client';
88
import { tcls } from '@/lib/tailwind';
9-
10-
import { useScrollListener } from '../hooks/useScrollListener';
11-
12-
const globalClassName = 'navigation-open';
13-
14-
const SCROLL_DISTANCE = 320;
9+
import type { GitBookSiteContext } from '@v2/lib/context';
10+
import { usePathname } from 'next/navigation';
1511

1612
/**
1713
* Button to show/hide the table of content on mobile.
1814
*/
19-
export function HeaderMobileMenu(props: Partial<React.ButtonHTMLAttributes<HTMLButtonElement>>) {
15+
export function HeaderMobileMenuButton({
16+
pages,
17+
...props
18+
}: Partial<React.ButtonHTMLAttributes<HTMLButtonElement>> & {
19+
pages: GitBookSiteContext['pages'];
20+
}) {
2021
const language = useLanguage();
21-
2222
const pathname = usePathname();
23-
const hasScrollRef = useRef(false);
23+
const { open, setOpen } = useMobileMenuSheet();
2424

2525
const toggleNavigation = () => {
26-
if (!hasScrollRef.current && document.body.classList.contains(globalClassName)) {
27-
document.body.classList.remove(globalClassName);
28-
} else {
29-
document.body.classList.add(globalClassName);
30-
window.scrollTo(0, 0);
31-
}
26+
setOpen(!open);
3227
};
3328

34-
const windowRef = useRef(typeof window === 'undefined' ? null : window);
35-
useScrollListener(() => {
36-
hasScrollRef.current = window.scrollY >= SCROLL_DISTANCE;
37-
}, windowRef);
38-
3929
// Close the navigation when navigating to a page
4030
useEffect(() => {
41-
document.body.classList.remove(globalClassName);
31+
if (!open) return;
32+
setOpen(false);
4233
}, [pathname]);
4334

4435
return (
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
'use client';
2+
3+
import { Sheet, SheetContent } from '@/components/utils/Sheet';
4+
import { useMobileMenuSheet } from './useMobileMenuSheet';
5+
6+
export function MobileMenuSheet({ children }: { children: React.ReactNode }) {
7+
const { open, setOpen } = useMobileMenuSheet();
8+
9+
return (
10+
<Sheet open={open} onOpenChange={setOpen}>
11+
<SheetContent
12+
aria-label="Mobile menu"
13+
overlayClassName="lg:hidden"
14+
className="pt-10 lg:hidden"
15+
>
16+
{children}
17+
</SheetContent>
18+
</Sheet>
19+
);
20+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { create } from 'zustand';
2+
3+
export const useMobileMenuSheet = create<{
4+
open: boolean;
5+
setOpen: (open: boolean) => void;
6+
}>((set) => ({
7+
open: false,
8+
setOpen: (open) => set({ open }),
9+
}));

packages/gitbook/src/components/SpaceLayout/SpaceLayout.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import { getSpaceLanguage } from '@/intl/server';
1111
import { t } from '@/intl/translate';
1212
import { tcls } from '@/lib/tailwind';
1313

14+
import { MobileMenuSheet } from '@/components/Header/mobile-menu/MobileMenuSheet';
15+
import { TOCScrollContent } from '@/components/TableOfContents/TOCScrollContent';
1416
import type { VisitorAuthClaims } from '@/lib/adaptive';
1517
import { GITBOOK_API_PUBLIC_URL, GITBOOK_APP_URL } from '@v2/lib/env';
1618
import { Announcement } from '../Announcement';
@@ -66,6 +68,9 @@ export function SpaceLayout(props: {
6668
>
6769
<Announcement context={context} />
6870
<Header withTopHeader={withTopHeader} context={context} />
71+
<MobileMenuSheet>
72+
<TOCScrollContent context={context} />
73+
</MobileMenuSheet>
6974
<div className="scroll-nojump">
7075
<div
7176
className={tcls(
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { PagesList } from '@/components/TableOfContents';
2+
import { Trademark } from '@/components/TableOfContents';
3+
import { TOCScrollContainer } from '@/components/TableOfContents/TOCScroller';
4+
import { tcls } from '@/lib/tailwind';
5+
import { SiteInsightsTrademarkPlacement } from '@gitbook/api';
6+
import type { GitBookSiteContext } from '@v2/lib/context';
7+
8+
export function TOCScrollContent(props: {
9+
context: GitBookSiteContext;
10+
innerHeader?: React.ReactNode;
11+
}) {
12+
const { context, innerHeader } = props;
13+
const { customization } = context;
14+
15+
return (
16+
<div // The actual sidebar, either shown with a filled bg or transparent.
17+
className={tcls(
18+
'lg:-ms-5',
19+
'relative flex flex-grow flex-col overflow-hidden border-tint-subtle',
20+
21+
'sidebar-filled:bg-tint-subtle',
22+
'theme-muted:bg-tint-subtle',
23+
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
24+
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
25+
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
26+
'[html.sidebar-filled.theme-gradient_&]:border',
27+
'page-no-toc:!bg-transparent',
28+
29+
'sidebar-filled:rounded-xl',
30+
'straight-corners:rounded-none'
31+
)}
32+
>
33+
{innerHeader && <div className="px-5 *:my-4">{innerHeader}</div>}
34+
35+
<TOCScrollContainer // The scrollview inside the sidebar
36+
className={tcls(
37+
'flex flex-grow flex-col p-2',
38+
customization.trademark.enabled && 'pb-20',
39+
'gutter-stable overflow-y-auto',
40+
'max-lg:[&::-webkit-scrollbar]:hidden',
41+
'[&::-webkit-scrollbar]:bg-transparent',
42+
'[&::-webkit-scrollbar-thumb]:bg-transparent',
43+
'group-hover:[&::-webkit-scrollbar]:bg-tint-subtle',
44+
'group-hover:[&::-webkit-scrollbar-thumb]:bg-tint-7',
45+
'group-hover:[&::-webkit-scrollbar-thumb:hover]:bg-tint-8'
46+
)}
47+
>
48+
<PagesList
49+
rootPages={context.pages}
50+
pages={context.pages}
51+
context={context}
52+
style="page-no-toc:hidden border-tint-subtle sidebar-list-line:border-l"
53+
/>
54+
{customization.trademark.enabled ? (
55+
<Trademark
56+
space={context.space}
57+
customization={customization}
58+
placement={SiteInsightsTrademarkPlacement.Sidebar}
59+
/>
60+
) : null}
61+
</TOCScrollContainer>
62+
</div>
63+
);
64+
}

packages/gitbook/src/components/TableOfContents/TableOfContents.tsx

Lines changed: 2 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
1-
import { SiteInsightsTrademarkPlacement } from '@gitbook/api';
21
import type { GitBookSiteContext } from '@v2/lib/context';
32
import type React from 'react';
43

4+
import { TOCScrollContent } from '@/components/TableOfContents/TOCScrollContent';
55
import { tcls } from '@/lib/tailwind';
6-
7-
import { PagesList } from './PagesList';
8-
import { TOCScrollContainer } from './TOCScroller';
96
import { TableOfContentsScript } from './TableOfContentsScript';
10-
import { Trademark } from './Trademark';
117

128
export function TableOfContents(props: {
139
context: GitBookSiteContext;
1410
header?: React.ReactNode; // Displayed outside the scrollable TOC as a sticky header
1511
innerHeader?: React.ReactNode; // Displayed outside the scrollable TOC, directly above the page list
1612
}) {
1713
const { innerHeader, context, header } = props;
18-
const { space, customization, pages } = context;
1914

2015
return (
2116
<>
@@ -59,64 +54,17 @@ export function TableOfContents(props: {
5954
'page-no-toc:lg:pr-0',
6055

6156
'hidden',
62-
'navigation-open:!flex',
6357
'lg:flex',
6458
'page-no-toc:lg:hidden',
6559
'page-no-toc:xl:flex',
6660
'site-header-none:page-no-toc:lg:flex',
6761
'flex-col',
6862
'gap-4',
69-
70-
'navigation-open:border-b',
7163
'border-tint-subtle'
7264
)}
7365
>
7466
{header && header}
75-
<div // The actual sidebar, either shown with a filled bg or transparent.
76-
className={tcls(
77-
'lg:-ms-5',
78-
'relative flex flex-grow flex-col overflow-hidden border-tint-subtle',
79-
80-
'sidebar-filled:bg-tint-subtle',
81-
'theme-muted:bg-tint-subtle',
82-
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
83-
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
84-
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
85-
'[html.sidebar-filled.theme-gradient_&]:border',
86-
'page-no-toc:!bg-transparent',
87-
88-
'sidebar-filled:rounded-xl',
89-
'straight-corners:rounded-none'
90-
)}
91-
>
92-
{innerHeader && <div className="px-5 *:my-4">{innerHeader}</div>}
93-
<TOCScrollContainer // The scrollview inside the sidebar
94-
className={tcls(
95-
'flex flex-grow flex-col p-2',
96-
customization.trademark.enabled && 'lg:pb-20',
97-
'lg:gutter-stable overflow-y-auto',
98-
'[&::-webkit-scrollbar]:bg-transparent',
99-
'[&::-webkit-scrollbar-thumb]:bg-transparent',
100-
'group-hover:[&::-webkit-scrollbar]:bg-tint-subtle',
101-
'group-hover:[&::-webkit-scrollbar-thumb]:bg-tint-7',
102-
'group-hover:[&::-webkit-scrollbar-thumb:hover]:bg-tint-8'
103-
)}
104-
>
105-
<PagesList
106-
rootPages={pages}
107-
pages={pages}
108-
context={context}
109-
style="page-no-toc:hidden border-tint-subtle sidebar-list-line:border-l"
110-
/>
111-
{customization.trademark.enabled ? (
112-
<Trademark
113-
space={space}
114-
customization={customization}
115-
placement={SiteInsightsTrademarkPlacement.Sidebar}
116-
/>
117-
) : null}
118-
</TOCScrollContainer>
119-
</div>
67+
<TOCScrollContent context={context} innerHeader={innerHeader} />
12068
</aside>
12169
<TableOfContentsScript />
12270
</>

packages/gitbook/src/components/TableOfContents/Trademark.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,17 @@ export function Trademark(props: {
2121
return (
2222
<div
2323
className={tcls(
24-
'relative',
2524
'z-[2]',
26-
'lg:absolute',
25+
'absolute',
2726

28-
'left-0',
27+
'lg:left-0',
28+
'left-2',
2929
'right-2',
3030
'bottom-0',
3131

32+
'py-2',
33+
'lg:py-0',
34+
3235
'pointer-events-none',
3336
'sidebar-filled:pl-2',
3437
'sidebar-filled:pb-2',
@@ -106,8 +109,7 @@ export function TrademarkLink(props: {
106109
'hover:bg-tint',
107110
'hover:text-tint-strong',
108111

109-
'ring-2',
110-
'lg:ring-1',
112+
'ring-1',
111113
'ring-inset',
112114
'ring-tint-subtle',
113115

0 commit comments

Comments
 (0)