diff --git a/e2e/pages.spec.ts b/e2e/pages.spec.ts
index 330dfa97e..b74c30bab 100644
--- a/e2e/pages.spec.ts
+++ b/e2e/pages.spec.ts
@@ -106,6 +106,93 @@ const testCases: TestsCase[] = [
},
],
},
+ {
+ name: 'GitBook Site (Navigation when switching variant)',
+ baseUrl: 'https://gitbook-open-e2e-sites.gitbook.io/',
+ tests: [
+ {
+ name: 'Keep navigation path/route when switching variant (Public)',
+ url: 'api-multi-versions/reference/api-reference/pets',
+ screenshot: false,
+ run: async (page) => {
+ const spaceDrowpdown = await page.waitForSelector(
+ '[data-testid="space-dropdown-button"]',
+ );
+ await spaceDrowpdown.click();
+
+ // Click the second variant in the dropdown
+ await page
+ .getByRole('link', {
+ name: '2.0',
+ })
+ .click();
+
+ // It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
+ await page.waitForURL(
+ 'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions/v/2.0/reference/api-reference/pets',
+ );
+ },
+ },
+ {
+ name: 'Keep navigation path/route when switching variant (Share link)',
+ url: 'api-multi-versions-share-links/bRfQbzwsK8rbN1GRxx7K/reference/api-reference/pets',
+ screenshot: false,
+ run: async (page) => {
+ const spaceDrowpdown = await page.waitForSelector(
+ '[data-testid="space-dropdown-button"]',
+ );
+ await spaceDrowpdown.click();
+
+ // Click the second variant in the dropdown
+ await page
+ .getByRole('link', {
+ name: '2.0',
+ })
+ .click();
+
+ // It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
+ await page.waitForURL(
+ 'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-share-links/bRfQbzwsK8rbN1GRxx7K/v/2.0/reference/api-reference/pets',
+ );
+ },
+ },
+ {
+ name: 'Keep navigation path/route when switching variant (VA)',
+ screenshot: false,
+ url: (() => {
+ const privateKey = 'c26190fc-74b2-4b54-9fc7-df9941104953';
+ const token = jwt.sign(
+ {
+ name: 'gitbook-open-tests',
+ },
+ privateKey,
+ {
+ expiresIn: '24h',
+ },
+ );
+ return `api-multi-versions-va/reference/api-reference/pets?jwt_token=${token}`;
+ })(),
+ run: async (page) => {
+ const spaceDrowpdown = await page.waitForSelector(
+ '[data-testid="space-dropdown-button"]',
+ );
+ await spaceDrowpdown.click();
+
+ // Click the second variant in the dropdown
+ await page
+ .getByRole('link', {
+ name: '2.0',
+ })
+ .click();
+
+ // It should keep the current page path, i.e "reference/api-reference/pets" when navigating to the new variant
+ await page.waitForURL(
+ 'https://gitbook-open-e2e-sites.gitbook.io/api-multi-versions-va/v/2.0/reference/api-reference/pets',
+ );
+ },
+ },
+ ],
+ },
{
name: 'GitBook',
baseUrl: 'https://docs.gitbook.com',
diff --git a/src/components/Header/SpacesDropdown.tsx b/src/components/Header/SpacesDropdown.tsx
index 19743fc22..6b5434abd 100644
--- a/src/components/Header/SpacesDropdown.tsx
+++ b/src/components/Header/SpacesDropdown.tsx
@@ -1,8 +1,9 @@
-import { Collection, Space } from '@gitbook/api';
+import { Space } from '@gitbook/api';
import { tcls } from '@/lib/tailwind';
-import { Dropdown, DropdownChevron, DropdownMenu, DropdownMenuItem } from './Dropdown';
+import { Dropdown, DropdownChevron, DropdownMenu } from './Dropdown';
+import { SpacesDropdownMenuItem } from './SpacesDropdownMenuItem';
export function SpacesDropdown(props: { space: Space; spaces: Space[] }) {
const { space, spaces } = props;
@@ -29,14 +30,12 @@ export function SpacesDropdown(props: { space: Space; spaces: Space[] }) {
)}
>
- {spaces.map((otherSpace) => (
-
- {otherSpace.title}
-
+ {spaces.map((otherSpace, index) => (
+
))}
diff --git a/src/components/Header/SpacesDropdownMenuItem.tsx b/src/components/Header/SpacesDropdownMenuItem.tsx
new file mode 100644
index 000000000..fd07b0543
--- /dev/null
+++ b/src/components/Header/SpacesDropdownMenuItem.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { Space } from '@gitbook/api';
+import { useSelectedLayoutSegment } from 'next/navigation';
+
+import { DropdownMenuItem } from './Dropdown';
+
+function useVariantSpaceHref(variantSpace: Space) {
+ const currentPathname = useSelectedLayoutSegment() ?? '';
+ const targetUrl = new URL(variantSpace.urls.published ?? variantSpace.urls.app);
+ targetUrl.pathname += `/${currentPathname}`;
+ targetUrl.pathname = targetUrl.pathname.replace(/\/{2,}/g, '/').replace(/\/$/, '');
+
+ return targetUrl.toString();
+}
+
+export function SpacesDropdownMenuItem(props: { variantSpace: Space; currentSpace: Space }) {
+ const { variantSpace, currentSpace } = props;
+ const variantHref = useVariantSpaceHref(variantSpace);
+
+ return (
+
+ {variantSpace.title}
+
+ );
+}