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 diff --git a/packages/gitbook-v2/src/lib/data/pages.ts b/packages/gitbook-v2/src/lib/data/pages.ts index 642b486b82..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)) { - 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; 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', diff --git a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx index e4465b3032..0638e5ba12 100644 --- a/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx +++ b/packages/gitbook/src/components/DocumentView/Tabs/DynamicTabs.tsx @@ -84,6 +84,9 @@ export function DynamicTabs( ); }, [id, tabs, tabsState]); + 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. // Otherwise because of the streaming/suspense approach, tabs can be first-rendered at different time @@ -143,110 +146,121 @@ export function DynamicTabs( return (
3 ? 'md:flex-wrap' : '', + + 'overflow-x-auto', + 'md:overflow-hidden', + + 'gap-1', + 'pb-2', 'flex-row', - 'self-stretch', - 'after:flex-[1]', - 'after:bg-tint-12/1', - // if last tab is selected, apply rounded to :after element - '[&:has(button.active-tab:last-of-type):after]:rounded-bl-md' + + 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) => ( - +
{tab.title}
+ +
+ {description ? ( + {description} + ) : null} + ))}
{tabs.map((tab, index) => ( @@ -255,7 +269,18 @@ 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', + 'flex-1', + 'straight-corners:rounded-none', + 'circular-corners:rounded-2xl', + 'grow', + 'ring-1', + 'ring-inset', + 'ring-tint-subtle', + tab.id !== active.id ? 'hidden' : null + )} > {tabsBody[index]} diff --git a/packages/gitbook/src/lib/waitUntil.ts b/packages/gitbook/src/lib/waitUntil.ts index e81e662e2d..dbaae41a0d 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,25 @@ 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; - } + await promise.catch((error) => { + console.error('Ignored error in waitUntil', error); + }); } /**