From 8e75e3bec579a0586f0b98ed94fca006e8d88aa9 Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Wed, 11 Jun 2025 16:50:09 +0200 Subject: [PATCH 01/10] First iteration --- .../DocumentView/Tabs/DynamicTabs.tsx | 142 +++++++++++------- 1 file changed, 84 insertions(+), 58 deletions(-) diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index e4465b3032..8c69669753 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -84,6 +84,8 @@ export function DynamicTabs( ); }, [id, tabs, tabsState]); + const position: string = 'top'; + // To avoid issue with hydration, we only use the state from localStorage // once the component has been mounted. // Otherwise because of the streaming/suspense approach, tabs can be first-rendered at different time @@ -143,13 +145,14 @@ export function DynamicTabs( return (
{tabs.map((tab) => ( @@ -174,49 +180,41 @@ export function DynamicTabs( hashLinkButtonWrapperStyles, 'flex', 'items-center', - 'gap-3.5', + 'relative', + position === 'left' && 'pr-1.5', + position === 'right' && 'pl-1.5', + position === 'top' && 'max-w-full overflow-hidden pb-1.5', + 'min-w-16', //prev from active-tab - '[&:has(+_.active-tab)]:rounded-br-md', + // '[&:has(+_.active-tab)]:rounded-br-md', //next from active-tab - '[.active-tab_+_&]:rounded-bl-md', + // '[.active-tab_+_&]:rounded-bl-md', //next from active-tab - '[.active-tab_+_:after]:rounded-br-md', - - 'after:transition-colors', - 'after:border-r', - 'after:absolute', - 'after:left-[unset]', - 'after:right-0', - 'after:border-tint', - 'after:top-[15%]', - 'after:h-[70%]', - 'after:w-[1px]', + // '[.active-tab_+_:after]:rounded-br-md', - 'px-3.5', - 'py-2', + // 'after:transition-colors', + // 'after:border-r', + // 'after:absolute', + // 'after:left-[unset]', + // 'after:right-0', + // 'after:border-tint', + // 'after:top-[15%]', + // 'after:h-[70%]', + // 'after:w-[1px]', - 'last:after:border-transparent', + // 'last:after:border-transparent', 'text-tint', - 'bg-tint-12/1', - 'hover:text-tint-strong', - 'max-w-full', - 'truncate', - - active.id === tab.id - ? [ - 'shrink-0', - 'active-tab', - 'text-tint-strong', - 'bg-transparent', - 'after:[&.active-tab]:border-transparent', - 'after:[:has(+_&.active-tab)]:border-transparent', - 'after:[:has(&_+)]:border-transparent', - ] - : null + // 'bg-tint-subtle', + // 'bg-tint-12/1', + // 'hover:text-tint-strong', + 'text-sm', + 'font-medium', + + active.id === tab.id ? 'active-tab text-primary-subtle' : '' )} > - + {active.id === tab.id ? ( +
+ ) : null}
))}
@@ -255,7 +271,17 @@ export function DynamicTabs( role="tabpanel" id={getTabPanelId(tab.id)} aria-labelledby={getTabButtonId(tab.id)} - className={tcls('p-4', tab.id !== active.id ? 'hidden' : null)} + className={tcls( + 'p-4', + 'rounded-lg', + 'straight-corners:rounded-none', + 'circular-corners:rounded-2xl', + 'grow', + 'ring-1', + 'ring-inset', + 'ring-tint-subtle', + tab.id !== active.id ? 'hidden' : null + )} > {tabsBody[index]} From 8e3e5147cf4be97d87100d613960b1df57bead25 Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Thu, 12 Jun 2025 19:38:31 +0200 Subject: [PATCH 02/10] Second iteration, ready --- .../DocumentView/Tabs/DynamicTabs.tsx | 175 +++++++++--------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index 8c69669753..0638e5ba12 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -84,7 +84,8 @@ export function DynamicTabs( ); }, [id, tabs, tabsState]); - const position: string = 'top'; + const position: string = 'top'; // TODO: Get position from tab block options + const description = null; // TODO: Get description from tabs // To avoid issue with hydration, we only use the state from localStorage // once the component has been mounted. @@ -145,16 +146,23 @@ export function DynamicTabs( return (
3 ? 'md:flex-wrap' : '', + + 'overflow-x-auto', + 'md:overflow-hidden', + + 'gap-1', + 'pb-2', + 'flex-row', + + position === 'left' || position === 'right' + ? 'gap-2 md:max-w-[40%] md:flex-col' + : '', + 'snap-x', + 'snap-mandatory', + + // We need to inset the tablist to make edge-to-edge scrolling work. + '-mx-4', + 'px-4', + 'scroll-px-4', + 'sm:-mx-6', + 'sm:px-6', + 'sm:scroll-px-6', + 'md:mx-0', + 'md:px-0', + 'md:scroll-px-0' )} > {tabs.map((tab) => ( - + ))}
{tabs.map((tab, index) => ( @@ -274,6 +272,7 @@ export function DynamicTabs( className={tcls( 'p-4', 'rounded-lg', + 'flex-1', 'straight-corners:rounded-none', 'circular-corners:rounded-2xl', 'grow', From 60015f58078be6548c8a7ccb7d6aaec5b3b8cd96 Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Thu, 12 Jun 2025 19:39:12 +0200 Subject: [PATCH 03/10] Changeset --- .changeset/tough-lobsters-perform.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tough-lobsters-perform.md diff --git a/.changeset/tough-lobsters-perform.md b/.changeset/tough-lobsters-perform.md new file mode 100644 index 0000000000..ea3debd6a4 --- /dev/null +++ b/.changeset/tough-lobsters-perform.md @@ -0,0 +1,5 @@ +--- +"gitbook": minor +--- + +New design for tab blocks From da67711c90f93c281a7ca650fd78ac073d60db30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Thu, 12 Jun 2025 23:37:38 +0200 Subject: [PATCH 04/10] Fix crash on Vercel (#3311) --- packages/gitbook-v2/src/lib/data/pages.ts | 2 +- packages/gitbook/src/lib/waitUntil.ts | 33 ++++++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/packages/gitbook-v2/src/lib/data/pages.ts b/packages/gitbook-v2/src/lib/data/pages.ts index 642b486b82..f4cbb1acab 100644 --- a/packages/gitbook-v2/src/lib/data/pages.ts +++ b/packages/gitbook-v2/src/lib/data/pages.ts @@ -42,7 +42,7 @@ export async function getPageDocument( } // Pre-fetch the document to start filling the cache before we migrate to this API. - if (isInPercentRollout(space.id, 10)) { + if (isInPercentRollout(space.id, 10) || process.env.VERCEL_ENV === 'preview') { await waitUntil( getDataOrNull( dataFetcher.getRevisionPageDocument({ diff --git a/packages/gitbook/src/lib/waitUntil.ts b/packages/gitbook/src/lib/waitUntil.ts index e81e662e2d..ed606e959d 100644 --- a/packages/gitbook/src/lib/waitUntil.ts +++ b/packages/gitbook/src/lib/waitUntil.ts @@ -1,5 +1,6 @@ import type { ExecutionContext, IncomingRequestCfProperties } from '@cloudflare/workers-types'; import { getCloudflareContext as getCloudflareContextV2 } from '@v2/lib/data/cloudflare'; +import { GITBOOK_RUNTIME } from '@v2/lib/env'; import { isV2 } from './v2'; let pendings: Array> = []; @@ -49,20 +50,32 @@ export async function waitUntil(promise: Promise) { return; } - if (isV2()) { - const context = getCloudflareContextV2(); - if (context) { - context.ctx.waitUntil(promise); - return; + if (GITBOOK_RUNTIME === 'cloudflare') { + if (isV2()) { + const context = getCloudflareContextV2(); + if (context) { + context.ctx.waitUntil(promise); + return; + } + } else { + const cloudflareContext = await getGlobalContext(); + if ('waitUntil' in cloudflareContext) { + cloudflareContext.waitUntil(promise); + return; + } } } - const cloudflareContext = await getGlobalContext(); - if ('waitUntil' in cloudflareContext) { - cloudflareContext.waitUntil(promise); - } else { - await promise; + if (GITBOOK_RUNTIME === 'vercel' && isV2()) { + // @ts-expect-error - `after` is not exported by `next/server` in next 14 + const { after } = await import('next/server'); + if (typeof after === 'function') { + after(() => promise); + return; + } } + + await promise; } /** From 315717fa2d219f3571eaf3a7bbbef418066d1da0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Fri, 13 Jun 2025 11:17:33 +0200 Subject: [PATCH 05/10] Disable the background fetch of getRevisionPageDocument (#3313) --- packages/gitbook-v2/src/lib/data/pages.ts | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/gitbook-v2/src/lib/data/pages.ts b/packages/gitbook-v2/src/lib/data/pages.ts index f4cbb1acab..b9e3cabc5e 100644 --- a/packages/gitbook-v2/src/lib/data/pages.ts +++ b/packages/gitbook-v2/src/lib/data/pages.ts @@ -42,16 +42,19 @@ export async function getPageDocument( } // Pre-fetch the document to start filling the cache before we migrate to this API. - if (isInPercentRollout(space.id, 10) || process.env.VERCEL_ENV === 'preview') { - await waitUntil( - getDataOrNull( - dataFetcher.getRevisionPageDocument({ - spaceId: space.id, - revisionId: space.revision, - pageId: page.id, - }) - ) - ); + if (process.env.NODE_ENV === 'development') { + // Disable for now to investigate side-effects + if (isInPercentRollout(space.id, 10) || process.env.VERCEL_ENV === 'preview') { + await waitUntil( + getDataOrNull( + dataFetcher.getRevisionPageDocument({ + spaceId: space.id, + revisionId: space.revision, + pageId: page.id, + }) + ) + ); + } } return null; From 50e8b2ec52e74dcb00d895c25b43bcf7971b855f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samy=20Pess=C3=A9?= Date: Fri, 13 Jun 2025 11:30:18 +0200 Subject: [PATCH 06/10] Don't use next/server after (#3314) --- packages/gitbook/src/lib/waitUntil.ts | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/packages/gitbook/src/lib/waitUntil.ts b/packages/gitbook/src/lib/waitUntil.ts index ed606e959d..dbaae41a0d 100644 --- a/packages/gitbook/src/lib/waitUntil.ts +++ b/packages/gitbook/src/lib/waitUntil.ts @@ -66,16 +66,9 @@ export async function waitUntil(promise: Promise) { } } - if (GITBOOK_RUNTIME === 'vercel' && isV2()) { - // @ts-expect-error - `after` is not exported by `next/server` in next 14 - const { after } = await import('next/server'); - if (typeof after === 'function') { - after(() => promise); - return; - } - } - - await promise; + await promise.catch((error) => { + console.error('Ignored error in waitUntil', error); + }); } /** From 28a9ee701e17a256387a301a078b5310c283d530 Mon Sep 17 00:00:00 2001 From: spastorelli Date: Fri, 13 Jun 2025 12:10:10 +0200 Subject: [PATCH 07/10] Add paypal.gitbook.com to ADAPTIVE_CONTENT_HOSTS list (#3315) --- packages/gitbook-v2/src/middleware.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/gitbook-v2/src/middleware.ts b/packages/gitbook-v2/src/middleware.ts index c11d466c78..0d57ce27e2 100644 --- a/packages/gitbook-v2/src/middleware.ts +++ b/packages/gitbook-v2/src/middleware.ts @@ -39,6 +39,7 @@ type URLWithMode = { url: URL; mode: 'url' | 'url-host' }; */ const ADAPTIVE_CONTENT_HOSTS = [ 'docs.gitbook.com', + 'paypal.gitbook.com', 'adaptive-docs.gitbook-staging.com', 'enriched-content-playground.gitbook-staging.io', 'docs.testgitbook.com', From 34a11d37a739ba344a9a6d5227526b4b7015fdaf Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Wed, 11 Jun 2025 16:50:09 +0200 Subject: [PATCH 08/10] First iteration --- .../DocumentView/Tabs/DynamicTabs.tsx | 142 +++++++++++------- 1 file changed, 84 insertions(+), 58 deletions(-) diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index e4465b3032..8c69669753 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -84,6 +84,8 @@ export function DynamicTabs( ); }, [id, tabs, tabsState]); + const position: string = 'top'; + // To avoid issue with hydration, we only use the state from localStorage // once the component has been mounted. // Otherwise because of the streaming/suspense approach, tabs can be first-rendered at different time @@ -143,13 +145,14 @@ export function DynamicTabs( return (
{tabs.map((tab) => ( @@ -174,49 +180,41 @@ export function DynamicTabs( hashLinkButtonWrapperStyles, 'flex', 'items-center', - 'gap-3.5', + 'relative', + position === 'left' && 'pr-1.5', + position === 'right' && 'pl-1.5', + position === 'top' && 'max-w-full overflow-hidden pb-1.5', + 'min-w-16', //prev from active-tab - '[&:has(+_.active-tab)]:rounded-br-md', + // '[&:has(+_.active-tab)]:rounded-br-md', //next from active-tab - '[.active-tab_+_&]:rounded-bl-md', + // '[.active-tab_+_&]:rounded-bl-md', //next from active-tab - '[.active-tab_+_:after]:rounded-br-md', - - 'after:transition-colors', - 'after:border-r', - 'after:absolute', - 'after:left-[unset]', - 'after:right-0', - 'after:border-tint', - 'after:top-[15%]', - 'after:h-[70%]', - 'after:w-[1px]', + // '[.active-tab_+_:after]:rounded-br-md', - 'px-3.5', - 'py-2', + // 'after:transition-colors', + // 'after:border-r', + // 'after:absolute', + // 'after:left-[unset]', + // 'after:right-0', + // 'after:border-tint', + // 'after:top-[15%]', + // 'after:h-[70%]', + // 'after:w-[1px]', - 'last:after:border-transparent', + // 'last:after:border-transparent', 'text-tint', - 'bg-tint-12/1', - 'hover:text-tint-strong', - 'max-w-full', - 'truncate', - - active.id === tab.id - ? [ - 'shrink-0', - 'active-tab', - 'text-tint-strong', - 'bg-transparent', - 'after:[&.active-tab]:border-transparent', - 'after:[:has(+_&.active-tab)]:border-transparent', - 'after:[:has(&_+)]:border-transparent', - ] - : null + // 'bg-tint-subtle', + // 'bg-tint-12/1', + // 'hover:text-tint-strong', + 'text-sm', + 'font-medium', + + active.id === tab.id ? 'active-tab text-primary-subtle' : '' )} > - + {active.id === tab.id ? ( +
+ ) : null}
))}
@@ -255,7 +271,17 @@ export function DynamicTabs( role="tabpanel" id={getTabPanelId(tab.id)} aria-labelledby={getTabButtonId(tab.id)} - className={tcls('p-4', tab.id !== active.id ? 'hidden' : null)} + className={tcls( + 'p-4', + 'rounded-lg', + 'straight-corners:rounded-none', + 'circular-corners:rounded-2xl', + 'grow', + 'ring-1', + 'ring-inset', + 'ring-tint-subtle', + tab.id !== active.id ? 'hidden' : null + )} > {tabsBody[index]}
From 17df1be3ef1620e9d5e35d05c4213feefb6de83e Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Thu, 12 Jun 2025 19:38:31 +0200 Subject: [PATCH 09/10] Second iteration, ready --- .../DocumentView/Tabs/DynamicTabs.tsx | 175 +++++++++--------- 1 file changed, 87 insertions(+), 88 deletions(-) diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index 8c69669753..0638e5ba12 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -84,7 +84,8 @@ export function DynamicTabs( ); }, [id, tabs, tabsState]); - const position: string = 'top'; + const position: string = 'top'; // TODO: Get position from tab block options + const description = null; // TODO: Get description from tabs // To avoid issue with hydration, we only use the state from localStorage // once the component has been mounted. @@ -145,16 +146,23 @@ export function DynamicTabs( return (
3 ? 'md:flex-wrap' : '', + + 'overflow-x-auto', + 'md:overflow-hidden', + + 'gap-1', + 'pb-2', + 'flex-row', + + position === 'left' || position === 'right' + ? 'gap-2 md:max-w-[40%] md:flex-col' + : '', + 'snap-x', + 'snap-mandatory', + + // We need to inset the tablist to make edge-to-edge scrolling work. + '-mx-4', + 'px-4', + 'scroll-px-4', + 'sm:-mx-6', + 'sm:px-6', + 'sm:scroll-px-6', + 'md:mx-0', + 'md:px-0', + 'md:scroll-px-0' )} > {tabs.map((tab) => ( - + ))}
{tabs.map((tab, index) => ( @@ -274,6 +272,7 @@ export function DynamicTabs( className={tcls( 'p-4', 'rounded-lg', + 'flex-1', 'straight-corners:rounded-none', 'circular-corners:rounded-2xl', 'grow', From e2dd8a92882e8ae7b7400e953cdff89fec033b2d Mon Sep 17 00:00:00 2001 From: Zeno Kapitein Date: Thu, 12 Jun 2025 19:39:12 +0200 Subject: [PATCH 10/10] Changeset --- .changeset/tough-lobsters-perform.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tough-lobsters-perform.md diff --git a/.changeset/tough-lobsters-perform.md b/.changeset/tough-lobsters-perform.md new file mode 100644 index 0000000000..ea3debd6a4 --- /dev/null +++ b/.changeset/tough-lobsters-perform.md @@ -0,0 +1,5 @@ +--- +"gitbook": minor +--- + +New design for tab blocks