Skip to content

Commit 9e669f1

Browse files
committed
Add SideSheet component, refactor TOC and AIChat to use it
Also fixes RND-7803
1 parent b49caaf commit 9e669f1

File tree

12 files changed

+227
-54
lines changed

12 files changed

+227
-54
lines changed

packages/gitbook/src/components/AIChat/AIChat.tsx

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { useTrackEvent } from '../Insights';
2626
import { useNow } from '../hooks';
2727
import { Button } from '../primitives';
2828
import { ScrollContainer } from '../primitives/ScrollContainer';
29+
import { SideSheet } from '../primitives/SideSheet';
2930
import { AIChatControlButton } from './AIChatControlButton';
3031
import { AIChatIcon } from './AIChatIcon';
3132
import { AIChatInput } from './AIChatInput';
@@ -68,16 +69,17 @@ export function AIChat() {
6869
}, [chat.opened, trackEvent]);
6970

7071
return (
71-
<div
72+
<SideSheet
73+
side="right"
74+
open={chat.opened}
75+
onClose={() => chatController.close()}
7276
data-testid="ai-chat"
77+
withShim={true}
7378
className={tcls(
74-
'ai-chat inset-y-0 right-0 z-40 mx-auto flex max-w-3xl scroll-mt-36 px-4 py-4 transition-[width,opacity,margin,display] transition-discrete duration-300 sm:px-6 lg:fixed lg:w-80 lg:p-0 xl:w-96',
75-
chat.opened
76-
? 'lg:starting:ml-0 lg:starting:w-0 lg:starting:opacity-0'
77-
: 'hidden lg:ml-0 lg:w-0! lg:opacity-0'
79+
'ai-chat z-40 mx-auto not-hydrated:hidden w-96 max-w-full pl-8 transition-[width] duration-300 ease-quint lg:max-xl:w-80'
7880
)}
7981
>
80-
<EmbeddableFrame className="relative shrink-0 border-tint-subtle border-l to-tint-base transition-all duration-300 max-lg:circular-corners:rounded-3xl max-lg:rounded-corners:rounded-md max-lg:border lg:w-80 xl:w-96">
82+
<EmbeddableFrame className="relative shrink-0 border-tint-subtle border-l to-tint-base">
8183
<EmbeddableFrameHeader>
8284
<AIChatDynamicIcon trademark={config.trademark} />
8385
<EmbeddableFrameHeaderMain>
@@ -102,7 +104,7 @@ export function AIChat() {
102104
<AIChatBody chatController={chatController} chat={chat} />
103105
</EmbeddableFrameBody>
104106
</EmbeddableFrame>
105-
</div>
107+
</SideSheet>
106108
);
107109
}
108110

packages/gitbook/src/components/Cookies/CookiesToast.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
4141
aria-describedby={describedById}
4242
className={tcls(
4343
'fixed',
44-
'z-10',
44+
'z-50',
4545
'bg-tint-base',
4646
'rounded-sm',
4747
'straight-corners:rounded-none',
@@ -52,9 +52,9 @@ export function CookiesToast(props: { privacyPolicy?: string }) {
5252
'depth-flat:shadow-none',
5353
'p-4',
5454
'pr-8',
55-
'bottom-4',
56-
'right-4',
57-
'left-16',
55+
'bottom-[max(env(safe-area-inset-bottom),1rem)]',
56+
'right-[max(env(safe-area-inset-right),1rem)]',
57+
'left-[max(env(safe-area-inset-left),4rem)]',
5858
'max-w-md',
5959
'text-balance',
6060
'sm:left-auto',

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ export function Header(props: {
4242
`h-[${HEADER_HEIGHT_DESKTOP}px]`,
4343
'sticky',
4444
'top-0',
45+
'pt-[env(safe-area-inset-top)]',
4546
'z-30',
4647
'w-full',
4748
'flex-none',
48-
'shadow-[0px_1px_0px]',
49-
'shadow-tint-12/2',
49+
'border-b',
50+
'border-tint-subtle',
5051

5152
'bg-tint-base/9',
5253
'theme-muted:bg-tint-subtle/9',

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

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,7 @@ export function HeaderMobileMenu(props: Partial<React.ButtonHTMLAttributes<HTMLB
2323
const hasScrollRef = useRef(false);
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+
document.body.classList.toggle(globalClassName);
3227
};
3328

3429
const windowRef = useRef(typeof window === 'undefined' ? null : window);

packages/gitbook/src/components/RootLayout/CustomizationRootLayout.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export async function CustomizationRootLayout(props: {
9191
suppressHydrationWarning
9292
lang={customization.internationalization.locale}
9393
className={tcls(
94+
'gutter-stable',
9495
customization.styling.corners && `${customization.styling.corners}-corners`,
9596
'theme' in customization.styling && `theme-${customization.styling.theme}`,
9697
tintColor ? ' tint' : 'no-tint',
@@ -179,7 +180,7 @@ export async function CustomizationRootLayout(props: {
179180
}
180181
`}</style>
181182
</head>
182-
<body className={className}>
183+
<body className={tcls(className, 'sheet-open:overflow-hidden')}>
183184
<IconsProvider
184185
assetsURL={GITBOOK_ICONS_URL}
185186
assetsURLToken={GITBOOK_ICONS_TOKEN}

packages/gitbook/src/components/SiteLayout/SiteLayout.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export async function generateSiteLayoutViewport(context: GitBookSiteContext): P
100100
width: 'device-width',
101101
initialScale: 1,
102102
maximumScale: 1,
103+
viewportFit: 'cover',
103104
};
104105
}
105106

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ export function SpaceLayout(props: SpaceLayoutProps) {
128128
'lg:justify-center',
129129
CONTAINER_STYLE,
130130
'site-width-wide:max-w-screen-4xl',
131-
'hydrated:transition-[max-width] duration-300',
131+
'transition-[max-width] duration-300',
132132

133133
// Ensure the footer is display below the viewport even if the content is not enough
134134
withFooter && [

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ export function PageGroupItem(props: { page: ClientTOCPageGroup; isFirst?: boole
2525
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-subtle',
2626
'[html.sidebar-filled.theme-muted_&]:bg-tint-base',
2727
'[html.sidebar-filled.theme-bold.tint_&]:bg-tint-base',
28-
'[html.sidebar-default.theme-gradient_&]:bg-gradient-primary',
29-
'[html.sidebar-default.theme-gradient.tint_&]:bg-gradient-tint',
28+
'lg:[html.sidebar-default.theme-gradient_&]:bg-gradient-primary',
29+
'lg:[html.sidebar-default.theme-gradient.tint_&]:bg-gradient-tint',
3030
isFirst ? '-mt-6' : ''
3131
)}
3232
>

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

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ import { SiteInsightsTrademarkPlacement } from '@gitbook/api';
33
import type React from 'react';
44

55
import { tcls } from '@/lib/tailwind';
6+
import { SideSheet } from '../primitives/SideSheet';
67
import { PagesList } from './PagesList';
78
import { TOCScrollContainer } from './TOCScroller';
89
import { TableOfContentsScript } from './TableOfContentsScript';
910
import { Trademark } from './Trademark';
1011
import { encodeClientTableOfContents } from './encodeClientTableOfContents';
1112

13+
/**
14+
* Sidebar container, responsible for setting the right dimensions and position for the sidebar.
15+
*/
1216
export async function TableOfContents(props: {
1317
context: GitBookSiteContext;
1418
header?: React.ReactNode; // Displayed outside the scrollable TOC as a sticky header
@@ -21,23 +25,33 @@ export async function TableOfContents(props: {
2125

2226
return (
2327
<>
24-
<aside // Sidebar container, responsible for setting the right dimensions and position for the sidebar.
28+
<SideSheet
29+
side="left"
2530
data-testid="table-of-contents"
2631
id="table-of-contents"
32+
toggleClass="navigation-open"
33+
withShim={true}
34+
withCloseButton={true}
2735
className={tcls(
28-
'group',
36+
'group/table-of-contents',
2937
'text-sm',
3038

3139
'grow-0',
3240
'shrink-0',
33-
'basis-full',
34-
'lg:basis-72',
41+
42+
'max-w-72',
43+
'basis-72',
3544
'lg:page-no-toc:basis-56',
3645

37-
'relative',
38-
'z-1',
46+
'max-lg:not-sidebar-filled:bg-tint-base',
47+
'max-lg:not-sidebar-filled:border-r',
48+
'border-tint-subtle',
49+
50+
'lg:flex!',
51+
'lg:animate-none!',
3952
'lg:sticky',
4053
'lg:mr-12',
54+
'max-lg:pl-3',
4155

4256
// Server-side static positioning
4357
'lg:top-0',
@@ -59,22 +73,12 @@ export async function TableOfContents(props: {
5973
'lg:page-no-toc:[html[style*="--outline-top-offset"]_&]:top-(--outline-top-offset)!',
6074
'lg:page-no-toc:[html[style*="--outline-height"]_&]:top-(--outline-height)!',
6175

62-
'pt-4',
63-
'pb-4',
76+
'py-4',
6477
'lg:sidebar-filled:pr-6',
6578
'lg:page-no-toc:pr-0',
6679

67-
'hidden',
68-
'navigation-open:flex!',
69-
'lg:flex',
70-
'lg:page-no-toc:hidden',
71-
'xl:page-no-toc:flex',
72-
'lg:site-header-none:page-no-toc:flex',
7380
'flex-col',
74-
'gap-4',
75-
76-
'navigation-open:border-b',
77-
'border-tint-subtle'
81+
'gap-4'
7882
)}
7983
>
8084
{header && header}
@@ -122,7 +126,7 @@ export async function TableOfContents(props: {
122126
) : null}
123127
</TOCScrollContainer>
124128
</div>
125-
</aside>
129+
</SideSheet>
126130
<TableOfContentsScript />
127131
</>
128132
);

packages/gitbook/src/components/layout.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ export const HEADER_HEIGHT_DESKTOP = 64 as const;
99
* Style for the container to adapt between normal and full width.
1010
*/
1111
export const CONTAINER_STYLE: ClassValue = [
12-
'px-4',
13-
'sm:px-6',
14-
'md:px-8',
12+
'px-4 pl-[max(env(safe-area-inset-left),1rem)] pr-[max(env(safe-area-inset-right),1rem)]',
13+
'sm:px-6 sm:pl-[max(env(safe-area-inset-left),1.5rem)] sm:pr-[max(env(safe-area-inset-right),1.5rem)]',
14+
'md:px-8 md:pl-[max(env(safe-area-inset-left),2rem)] md:pr-[max(env(safe-area-inset-right),2rem)]',
1515
'max-w-screen-2xl',
1616
'mx-auto',
1717
];

0 commit comments

Comments
 (0)