Skip to content

Commit bef1916

Browse files
Allow hiding toolbar for one session or persistent (#3698)
1 parent 1456251 commit bef1916

File tree

12 files changed

+817
-183
lines changed

12 files changed

+817
-183
lines changed

packages/gitbook/src/components/AdminToolbar/AdminToolbarClient.tsx

Lines changed: 125 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { useCheckForContentUpdate } from '../AutoRefreshContent';
55
import { useVisitorSession } from '../Insights';
66
import { useCurrentPagePath } from '../hooks';
77
import { DateRelative } from '../primitives';
8+
import { HideToolbarButton } from './HideToolbarButton';
89
import { IframeWrapper } from './IframeWrapper';
910
import { RefreshContentButton } from './RefreshContentButton';
1011
import {
@@ -17,48 +18,108 @@ import {
1718
ToolbarSubtitle,
1819
ToolbarTitle,
1920
} from './Toolbar';
20-
import type { AdminToolbarClientProps } from './types';
21+
import {
22+
type ToolbarControlsContextValue,
23+
ToolbarControlsProvider,
24+
} from './ToolbarControlsContext';
25+
import type { AdminToolbarClientProps, AdminToolbarContext } from './types';
26+
import { useToolbarVisibility } from './utils';
2127

2228
export function AdminToolbarClient(props: AdminToolbarClientProps) {
23-
const { context } = props;
29+
const { context, onPersistentClose, onSessionClose, onToggleMinify } = props;
30+
const {
31+
minified,
32+
setMinified,
33+
shouldAutoExpand,
34+
hidden,
35+
minimize,
36+
closeSession,
37+
closePersistent,
38+
} = useToolbarVisibility({
39+
onPersistentClose,
40+
onSessionClose,
41+
onToggleMinify,
42+
});
43+
2444
const visitorSession = useVisitorSession();
2545

46+
const toolbarControls: ToolbarControlsContextValue = {
47+
minimize,
48+
closeSession,
49+
closePersistent,
50+
shouldAutoExpand,
51+
};
52+
53+
if (hidden) {
54+
return null;
55+
}
56+
2657
// If there is a change request, show the change request toolbar
2758
if (context.changeRequest) {
2859
return (
29-
<IframeWrapper>
30-
<MotionConfig reducedMotion="user">
31-
<ChangeRequestToolbar context={context} />
32-
</MotionConfig>
33-
</IframeWrapper>
60+
<ToolbarControlsWrapper value={toolbarControls}>
61+
<ChangeRequestToolbar
62+
context={context}
63+
minified={minified}
64+
onMinifiedChange={setMinified}
65+
/>
66+
</ToolbarControlsWrapper>
3467
);
3568
}
3669

3770
// If the revision is not the current revision, the user is looking at a previous version of the site, so show the revision toolbar
3871
if (context.revisionId !== context.space.revision) {
3972
return (
40-
<IframeWrapper>
41-
<MotionConfig reducedMotion="user">
42-
<RevisionToolbar context={context} />
43-
</MotionConfig>
44-
</IframeWrapper>
73+
<ToolbarControlsWrapper value={toolbarControls}>
74+
<RevisionToolbar
75+
context={context}
76+
minified={minified}
77+
onMinifiedChange={setMinified}
78+
/>
79+
</ToolbarControlsWrapper>
4580
);
4681
}
4782

4883
// If the user is authenticated and part of the organization owning this site, show the authenticated user toolbar
4984
if (visitorSession?.organizationId === context.organizationId) {
5085
return (
51-
<IframeWrapper>
52-
<MotionConfig reducedMotion="user">
53-
<AuthenticatedUserToolbar context={context} />
54-
</MotionConfig>
55-
</IframeWrapper>
86+
<ToolbarControlsWrapper value={toolbarControls}>
87+
<AuthenticatedUserToolbar
88+
context={context}
89+
minified={minified}
90+
onMinifiedChange={setMinified}
91+
/>
92+
</ToolbarControlsWrapper>
5693
);
5794
}
95+
96+
return null;
5897
}
5998

60-
function ChangeRequestToolbar(props: AdminToolbarClientProps) {
61-
const { context } = props;
99+
/**
100+
* Reusable wrapper that provides tooling and containers that are used by all types of toolbar views.
101+
*/
102+
export function ToolbarControlsWrapper(
103+
props: React.PropsWithChildren<{ value: ToolbarControlsContextValue | null }>
104+
) {
105+
const { children, value } = props;
106+
return (
107+
<ToolbarControlsProvider value={value}>
108+
<IframeWrapper>
109+
<MotionConfig reducedMotion="user">{children}</MotionConfig>
110+
</IframeWrapper>
111+
</ToolbarControlsProvider>
112+
);
113+
}
114+
115+
interface ToolbarViewProps {
116+
context: AdminToolbarContext;
117+
minified: boolean;
118+
onMinifiedChange: (value: boolean) => void;
119+
}
120+
121+
function ChangeRequestToolbar(props: ToolbarViewProps) {
122+
const { context, minified, onMinifiedChange } = props;
62123
const { changeRequest, site } = context;
63124
if (!changeRequest) {
64125
throw new Error('Change request is not set');
@@ -71,11 +132,11 @@ function ChangeRequestToolbar(props: AdminToolbarClientProps) {
71132
});
72133

73134
return (
74-
<Toolbar label="Site preview">
135+
<Toolbar minified={minified} onMinifiedChange={onMinifiedChange} label="Site preview">
75136
<ToolbarBody>
76137
<ToolbarTitle
77-
prefix="Change request"
78-
suffix={`#${changeRequest.number} ${changeRequest.subject || 'Untitled'}`}
138+
prefix={`Change #${changeRequest.number}:`}
139+
suffix={`${changeRequest.subject || 'Untitled'}`}
79140
/>
80141
<ToolbarSubtitle
81142
subtitle={
@@ -88,9 +149,13 @@ function ChangeRequestToolbar(props: AdminToolbarClientProps) {
88149

89150
<ToolbarSeparator />
90151

91-
<ToolbarButtonGroup>
152+
<ToolbarActions>
92153
{/* Refresh to retrieve latest changes */}
93154
{updated ? <RefreshContentButton refreshForUpdates={refreshForUpdates} /> : null}
155+
156+
{/* Edit in GitBook */}
157+
<EditPageButton href={changeRequest.urls.app} siteId={site.id} />
158+
94159
{/* Comment in app */}
95160
<ToolbarButton
96161
title="Comment in a GitBook"
@@ -125,16 +190,13 @@ function ChangeRequestToolbar(props: AdminToolbarClientProps) {
125190
})}
126191
icon="code-pull-request"
127192
/>
128-
129-
{/* Edit in GitBook */}
130-
<EditPageButton href={changeRequest.urls.app} siteId={site.id} />
131-
</ToolbarButtonGroup>
193+
</ToolbarActions>
132194
</Toolbar>
133195
);
134196
}
135197

136-
function RevisionToolbar(props: AdminToolbarClientProps) {
137-
const { context } = props;
198+
function RevisionToolbar(props: ToolbarViewProps) {
199+
const { context, minified, onMinifiedChange } = props;
138200
const { revision, site } = context;
139201
if (!revision) {
140202
throw new Error('Revision is not set');
@@ -145,7 +207,7 @@ function RevisionToolbar(props: AdminToolbarClientProps) {
145207
const gitProvider = isGitHub ? 'GitHub' : 'GitLab';
146208

147209
return (
148-
<Toolbar label="Site preview">
210+
<Toolbar minified={minified} onMinifiedChange={onMinifiedChange} label="Site preview">
149211
<ToolbarBody>
150212
<ToolbarTitle prefix="Site version" suffix={context.site.title} />
151213
<ToolbarSubtitle
@@ -157,7 +219,7 @@ function RevisionToolbar(props: AdminToolbarClientProps) {
157219
/>
158220
</ToolbarBody>
159221
<ToolbarSeparator />
160-
<ToolbarButtonGroup>
222+
<ToolbarActions>
161223
{/* Open commit in Git client */}
162224
<ToolbarButton
163225
title={
@@ -205,22 +267,26 @@ function RevisionToolbar(props: AdminToolbarClientProps) {
205267
})}
206268
icon="code-commit"
207269
/>
208-
</ToolbarButtonGroup>
270+
</ToolbarActions>
209271
</Toolbar>
210272
);
211273
}
212274

213-
function AuthenticatedUserToolbar(props: AdminToolbarClientProps) {
214-
const { context } = props;
275+
function AuthenticatedUserToolbar(props: ToolbarViewProps) {
276+
const { context, minified, onMinifiedChange } = props;
215277
const { revision, space, site } = context;
216278
const { refreshForUpdates, updated } = useCheckForContentUpdate({
217279
revisionId: space.revision,
218280
});
219281

220282
return (
221-
<Toolbar label="Only visible to your GitBook organization">
283+
<Toolbar
284+
minified={minified}
285+
onMinifiedChange={onMinifiedChange}
286+
label="Only visible to your GitBook organization"
287+
>
222288
<ToolbarBody>
223-
<ToolbarTitle prefix="Site" suffix={context.site.title} />
289+
<ToolbarTitle suffix={context.site.title} />
224290
<ToolbarSubtitle
225291
subtitle={
226292
<>
@@ -230,18 +296,25 @@ function AuthenticatedUserToolbar(props: AdminToolbarClientProps) {
230296
/>
231297
</ToolbarBody>
232298
<ToolbarSeparator />
233-
<ToolbarButtonGroup>
299+
<ToolbarActions>
234300
{/* Refresh to retrieve latest changes */}
235301
{updated ? <RefreshContentButton refreshForUpdates={refreshForUpdates} /> : null}
302+
303+
{/* Edit in GitBook */}
304+
<EditPageButton href={space.urls.app} siteId={site.id} />
305+
306+
{/* Open site in GitBook */}
236307
<ToolbarButton
237308
title="Open site in GitBook"
238309
href={getToolbarHref({
239310
href: site.urls.app,
240311
siteId: site.id,
241312
buttonId: 'site',
242313
})}
243-
icon="gear"
314+
icon="gears"
244315
/>
316+
317+
{/* Customize in GitBook */}
245318
<ToolbarButton
246319
title="Customize in GitBook"
247320
href={getToolbarHref({
@@ -251,6 +324,8 @@ function AuthenticatedUserToolbar(props: AdminToolbarClientProps) {
251324
})}
252325
icon="palette"
253326
/>
327+
328+
{/* Open insights in GitBook */}
254329
<ToolbarButton
255330
title="Open insights in GitBook"
256331
href={getToolbarHref({
@@ -260,12 +335,22 @@ function AuthenticatedUserToolbar(props: AdminToolbarClientProps) {
260335
})}
261336
icon="chart-simple"
262337
/>
263-
<EditPageButton href={space.urls.app} siteId={site.id} />
264-
</ToolbarButtonGroup>
338+
</ToolbarActions>
265339
</Toolbar>
266340
);
267341
}
268342

343+
function ToolbarActions(props: { children: React.ReactNode }) {
344+
const { children } = props;
345+
346+
return (
347+
<ToolbarButtonGroup>
348+
{children}
349+
<HideToolbarButton />
350+
</ToolbarButtonGroup>
351+
);
352+
}
353+
269354
function EditPageButton(props: {
270355
href: string;
271356
siteId: string;

packages/gitbook/src/components/AdminToolbar/AnimatedLogo.module.css

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,15 @@
1111
vector-effect: non-scaling-stroke;
1212
}
1313

14-
:global(html.dark) .svgLogo {
15-
--logo-fill: var(--color-neutral-800);
16-
--trace-color: #dedfe3;
14+
.static .trace {
15+
animation: none;
16+
fill: var(--logo-fill);
17+
stroke: none;
18+
}
19+
20+
.static .seg {
21+
animation: none;
22+
opacity: 0;
1723
}
1824

1925
/* Base segment animation */
@@ -176,4 +182,4 @@
176182
fill: var(--logo-fill);
177183
stroke:none;
178184
}
179-
}
185+
}

packages/gitbook/src/components/AdminToolbar/AnimatedLogo.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,16 @@ import { tcls } from '@/lib/tailwind';
22
import type React from 'react';
33
import styles from './AnimatedLogo.module.css';
44

5-
export const AnimatedLogo: React.FC = () => {
5+
interface AnimatedLogoProps {
6+
shouldAnimate?: boolean;
7+
}
8+
9+
export const AnimatedLogo: React.FC<AnimatedLogoProps> = (props) => {
10+
const { shouldAnimate = true } = props;
11+
612
return (
713
<svg
8-
className={styles.svgLogo}
14+
className={tcls(styles.svgLogo, shouldAnimate ? undefined : styles.static)}
915
width="28"
1016
height="28"
1117
viewBox="0 0 28 28"

0 commit comments

Comments
 (0)