From a625112106f2445bf892693471c5d4d54a94cefc Mon Sep 17 00:00:00 2001 From: Peter White <1788320+peterwhite@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:40:20 +0200 Subject: [PATCH] Skip the Ask AI paragraph button inside tables (#4680) --- .changeset/skip-ask-ai-in-tables.md | 5 ++++ .../src/components/DocumentView/Paragraph.tsx | 4 ++- .../DocumentView/Table/RecordColumnValue.tsx | 3 +- .../utils/isBlockOffscreen.test.ts | 30 ++++++++++++++++++- .../DocumentView/utils/isBlockOffscreen.ts | 5 ++++ 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 .changeset/skip-ask-ai-in-tables.md diff --git a/.changeset/skip-ask-ai-in-tables.md b/.changeset/skip-ask-ai-in-tables.md new file mode 100644 index 000000000..7db75cc14 --- /dev/null +++ b/.changeset/skip-ask-ai-in-tables.md @@ -0,0 +1,5 @@ +--- +"gitbook": patch +--- + +Skip rendering the Ask AI paragraph button inside table cells, where it is hidden, to keep pages with large tables within memory limits. diff --git a/packages/gitbook/src/components/DocumentView/Paragraph.tsx b/packages/gitbook/src/components/DocumentView/Paragraph.tsx index 6359f0026..4d80132fd 100644 --- a/packages/gitbook/src/components/DocumentView/Paragraph.tsx +++ b/packages/gitbook/src/components/DocumentView/Paragraph.tsx @@ -9,7 +9,7 @@ import { getNodeText } from '@/lib/document'; import { tcls } from '@/lib/tailwind'; export function Paragraph(props: BlockProps) { - const { block, style, ...contextProps } = props; + const { block, style, ancestorBlocks, ...contextProps } = props; const { context } = contextProps; const paragraph = ( @@ -28,6 +28,8 @@ export function Paragraph(props: BlockProps) { const contentContext = context.contentContext; const aiAssistantEnabled = context.mode !== 'print' && + // The button is hidden in table cells, and big tables can hold thousands of paragraphs. + !ancestorBlocks.some((ancestor) => ancestor.type === 'table') && contentContext != null && 'customization' in contentContext && contentContext.customization.ai.mode === CustomizationAIMode.Assistant; diff --git a/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx b/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx index 7c16b951a..b6641f046 100644 --- a/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx +++ b/packages/gitbook/src/components/DocumentView/Table/RecordColumnValue.tsx @@ -50,6 +50,7 @@ export async function RecordColumnValue( tag: Tag = 'div', ariaLabelledBy, block, + ancestorBlocks, document, record, column, @@ -151,7 +152,7 @@ export async function RecordColumnValue( { ) ).toBe(true); }); + +it('should treat content in table cells as offscreen', () => { + const cell: DocumentBlockParagraph = { + object: 'block', + type: 'paragraph', + nodes: [], + }; + + const table: DocumentBlockTable = { + object: 'block', + type: 'table', + isVoid: true, + data: { + view: { type: 'cards', cardSize: 'medium', columns: ['column'] }, + records: {}, + definition: {}, + }, + fragments: [{ object: 'fragment', fragment: 'cell', nodes: [cell] }], + }; + + const document: JSONDocument = { + object: 'document', + nodes: [table], + data: {}, + }; + + expect(isBlockOffscreen({ document, block: cell, ancestorBlocks: [table] })).toBe(true); +}); diff --git a/packages/gitbook/src/components/DocumentView/utils/isBlockOffscreen.ts b/packages/gitbook/src/components/DocumentView/utils/isBlockOffscreen.ts index c26738223..e3b5ec495 100644 --- a/packages/gitbook/src/components/DocumentView/utils/isBlockOffscreen.ts +++ b/packages/gitbook/src/components/DocumentView/utils/isBlockOffscreen.ts @@ -18,6 +18,11 @@ export function isBlockOffscreen( }, screenHeight = 500 ): boolean { + // Cell content lives in fragments, not table nodes, so its row position can't be estimated. + if (ancestorBlocks.some((ancestor) => ancestor.type === 'table')) { + return true; + } + let current = block; const allAncestors = [document, ...ancestorBlocks];