Skip to content

Commit c3b620e

Browse files
authored
Preserve current variant when navigating between sections (#3306)
1 parent 7a00880 commit c3b620e

File tree

4 files changed

+62
-21
lines changed

4 files changed

+62
-21
lines changed

.changeset/hip-bobcats-cover.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+
Best effort at preserving current variant when navigating between sections by matching the pathname against site spaces in the new section.

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

Lines changed: 2 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { SiteSpace } from '@gitbook/api';
22

3+
import { getSiteSpaceURL } from '@/lib/sites';
34
import { tcls } from '@/lib/tailwind';
4-
5-
import { joinPath } from '@/lib/paths';
65
import type { GitBookSiteContext } from '@v2/lib/context';
76
import { DropdownChevron, DropdownMenu } from './DropdownMenu';
87
import { SpacesDropdownMenuItem } from './SpacesDropdownMenuItem';
@@ -14,7 +13,6 @@ export function SpacesDropdown(props: {
1413
className?: string;
1514
}) {
1615
const { context, siteSpace, siteSpaces, className } = props;
17-
const { linker } = context;
1816

1917
return (
2018
<DropdownMenu
@@ -73,24 +71,11 @@ export function SpacesDropdown(props: {
7371
variantSpace={{
7472
id: otherSiteSpace.id,
7573
title: otherSiteSpace.title,
76-
url: otherSiteSpace.urls.published
77-
? linker.toLinkForContent(otherSiteSpace.urls.published)
78-
: getFallbackSiteSpaceURL(otherSiteSpace, context),
74+
url: getSiteSpaceURL(context, otherSiteSpace),
7975
}}
8076
active={otherSiteSpace.id === siteSpace.id}
8177
/>
8278
))}
8379
</DropdownMenu>
8480
);
8581
}
86-
87-
/**
88-
* When the site is not published yet, `urls.published` is not available.
89-
* To ensure navigation works in preview, we compute a relative URL from the siteSpace path.
90-
*/
91-
function getFallbackSiteSpaceURL(siteSpace: SiteSpace, context: GitBookSiteContext) {
92-
const { linker, sections } = context;
93-
return linker.toPathInSite(
94-
sections?.current ? joinPath(sections.current.path, siteSpace.path) : siteSpace.path
95-
);
96-
}

packages/gitbook/src/components/SiteSections/encodeClientSiteSections.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getSectionURL, getSiteSpaceURL } from '@/lib/sites';
12
import type { SiteSection, SiteSectionGroup } from '@gitbook/api';
23
import type { GitBookSiteContext, SiteSections } from '@v2/lib/context';
34

@@ -46,15 +47,35 @@ export function encodeClientSiteSections(context: GitBookSiteContext, sections:
4647
}
4748

4849
function encodeSection(context: GitBookSiteContext, section: SiteSection) {
49-
const { linker } = context;
5050
return {
5151
id: section.id,
5252
title: section.title,
5353
description: section.description,
5454
icon: section.icon,
5555
object: section.object,
56-
url: section.urls.published
57-
? linker.toLinkForContent(section.urls.published)
58-
: linker.toPathInSite(section.path),
56+
url: findBestTargetURL(context, section),
5957
};
6058
}
59+
60+
/**
61+
* Find the best default site space to navigate to for a givent section:
62+
* 1. If we are on the default, continue on the default.
63+
* 2. If a site space has the same path as the current one, return it.
64+
* 3. Otherwise, return the default one.
65+
*/
66+
function findBestTargetURL(context: GitBookSiteContext, section: SiteSection) {
67+
const { siteSpace: currentSiteSpace } = context;
68+
69+
if (section.siteSpaces.length === 1 || currentSiteSpace.default) {
70+
return getSectionURL(context, section);
71+
}
72+
73+
const bestMatch = section.siteSpaces.find(
74+
(siteSpace) => siteSpace.path === currentSiteSpace.path
75+
);
76+
if (bestMatch) {
77+
return getSiteSpaceURL(context, bestMatch);
78+
}
79+
80+
return getSectionURL(context, section);
81+
}

packages/gitbook/src/lib/sites.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import type { SiteSection, SiteSectionGroup, SiteSpace, SiteStructure } from '@gitbook/api';
2+
import type { GitBookSiteContext } from '@v2/lib/context';
3+
import { joinPath } from './paths';
24

35
/**
46
* Get all sections from a site structure.
@@ -64,6 +66,34 @@ export function findSiteSpaceById(siteStructure: SiteStructure, spaceId: string)
6466
return null;
6567
}
6668

69+
/**
70+
* Get the URL to navigate to for a section.
71+
* When the site is not published yet, `urls.published` is not available.
72+
* To ensure navigation works in preview, we compute a relative URL from the siteSection path.
73+
*/
74+
export function getSectionURL(context: GitBookSiteContext, section: SiteSection) {
75+
const { linker } = context;
76+
return section.urls.published
77+
? linker.toLinkForContent(section.urls.published)
78+
: linker.toPathInSite(section.path);
79+
}
80+
81+
/**
82+
* Get the URL to navigate to for a site space.
83+
* When the site is not published yet, `urls.published` is not available.
84+
* To ensure navigation works in preview, we compute a relative URL from the siteSpace path.
85+
*/
86+
export function getSiteSpaceURL(context: GitBookSiteContext, siteSpace: SiteSpace) {
87+
const { linker, sections } = context;
88+
if (siteSpace.urls.published) {
89+
return linker.toLinkForContent(siteSpace.urls.published);
90+
}
91+
92+
return linker.toPathInSite(
93+
sections?.current ? joinPath(sections.current.path, siteSpace.path) : siteSpace.path
94+
);
95+
}
96+
6797
function findSiteSpaceByIdInSections(sections: SiteSection[], spaceId: string): SiteSpace | null {
6898
for (const section of sections) {
6999
const siteSpace =

0 commit comments

Comments
 (0)