Skip to content

Commit 2a6792d

Browse files
authored
Merge branch 'main' into stevenh/bump-shiki
2 parents f84b722 + 39c4f76 commit 2a6792d

File tree

18 files changed

+140
-70
lines changed

18 files changed

+140
-70
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"gitbook": patch
3+
---
4+
5+
Add fullwidth page option

packages/gitbook/e2e/internal.spec.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,22 @@ const testCases: TestsCase[] = [
932932
},
933933
]),
934934
},
935+
{
936+
name: 'Page actions',
937+
contentBaseURL: 'https://gitbook.gitbook.io/test-gitbook-open/',
938+
tests: [
939+
{
940+
name: 'Without page actions',
941+
url: getCustomizationURL({
942+
pageActions: {
943+
markdown: false,
944+
externalAI: false,
945+
},
946+
}),
947+
run: waitForCookiesDialog,
948+
},
949+
],
950+
},
935951
{
936952
name: 'Ads',
937953
contentBaseURL: 'https://gitbook.gitbook.io/test-gitbook-open/',

packages/gitbook/src/components/AIActions/AIActionsDropdown.tsx

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
} from '@/components/AIActions/AIActions';
99
import { Button } from '@/components/primitives/Button';
1010
import { DropdownMenu } from '@/components/primitives/DropdownMenu';
11+
import type { SiteCustomizationSettings } from '@gitbook/api';
1112

1213
import { Icon } from '@gitbook/icons';
1314
import { useRef } from 'react';
@@ -16,10 +17,7 @@ interface AIActionsDropdownProps {
1617
markdownPageUrl: string;
1718
withAIChat?: boolean;
1819
trademark: boolean;
19-
/**
20-
* Whether to include the "Open in LLM" entries in the dropdown menu.
21-
*/
22-
withLLMActions?: boolean;
20+
actions: SiteCustomizationSettings['pageActions'];
2321
}
2422

2523
/**
@@ -59,22 +57,26 @@ export function AIActionsDropdown(props: AIActionsDropdownProps) {
5957
* The content of the dropdown menu.
6058
*/
6159
function AIActionsDropdownMenuContent(props: AIActionsDropdownProps) {
62-
const { markdownPageUrl, withAIChat, trademark, withLLMActions } = props;
60+
const { markdownPageUrl, withAIChat, trademark, actions } = props;
6361

6462
return (
6563
<>
6664
{withAIChat ? (
6765
<OpenDocsAssistant trademark={trademark} type="dropdown-menu-item" />
6866
) : null}
6967

70-
<CopyMarkdown
71-
isDefaultAction={!withAIChat}
72-
markdownPageUrl={markdownPageUrl}
73-
type="dropdown-menu-item"
74-
/>
75-
<ViewAsMarkdown markdownPageUrl={markdownPageUrl} type="dropdown-menu-item" />
68+
{actions.markdown ? (
69+
<>
70+
<CopyMarkdown
71+
isDefaultAction={!withAIChat}
72+
markdownPageUrl={markdownPageUrl}
73+
type="dropdown-menu-item"
74+
/>
75+
<ViewAsMarkdown markdownPageUrl={markdownPageUrl} type="dropdown-menu-item" />
76+
</>
77+
) : null}
7678

77-
{withLLMActions ? (
79+
{actions.externalAI ? (
7880
<>
7981
<OpenInLLM provider="chatgpt" url={markdownPageUrl} type="dropdown-menu-item" />
8082
<OpenInLLM provider="claude" url={markdownPageUrl} type="dropdown-menu-item" />
@@ -88,17 +90,27 @@ function AIActionsDropdownMenuContent(props: AIActionsDropdownProps) {
8890
* A default action shown as a quick-access button beside the dropdown menu
8991
*/
9092
function DefaultAction(props: AIActionsDropdownProps) {
91-
const { markdownPageUrl, withAIChat, trademark } = props;
93+
const { markdownPageUrl, withAIChat, trademark, actions } = props;
9294

9395
if (withAIChat) {
9496
return <OpenDocsAssistant trademark={trademark} type="button" />;
9597
}
9698

97-
return (
98-
<CopyMarkdown
99-
isDefaultAction={!withAIChat}
100-
markdownPageUrl={markdownPageUrl}
101-
type="button"
102-
/>
103-
);
99+
if (actions.markdown) {
100+
return (
101+
<CopyMarkdown
102+
isDefaultAction={!withAIChat}
103+
markdownPageUrl={markdownPageUrl}
104+
type="button"
105+
/>
106+
);
107+
}
108+
109+
if (actions.externalAI) {
110+
return (
111+
<>
112+
<OpenInLLM provider="chatgpt" url={markdownPageUrl} type="button" />
113+
</>
114+
);
115+
}
104116
}

packages/gitbook/src/components/DocumentView/Blocks.tsx

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ type UnwrappedBlocksProps<TBlock extends DocumentBlock> = DocumentContextProps &
4747
isOffscreen?: boolean;
4848
};
4949

50+
/* Blocks that can be full width are automatically expanded on full-width pages.
51+
* Ideally we'd rely on the block type to determine if it can be full width, but
52+
* the block's `fullWidth` property does not differentiate between `undefined` and `false`.
53+
* So instead we hardcode a list of blocks that can be full width. */
54+
const FULL_WIDTH_BLOCKS = [
55+
'table',
56+
'tabs',
57+
'integration',
58+
'openapi',
59+
'images',
60+
'embed',
61+
'columns',
62+
'code',
63+
'content-ref',
64+
'hint',
65+
];
66+
5067
/**
5168
* Renders a list of blocks without a wrapper element.
5269
*/
@@ -68,10 +85,11 @@ export function UnwrappedBlocks<TBlock extends DocumentBlock>(props: UnwrappedBl
6885
key={node.key || `${node.type}-${index}`}
6986
block={node}
7087
style={[
71-
'mx-auto w-full decoration-primary/6',
88+
'mx-auto page-width-wide:mx-0 w-full decoration-primary/6',
7289
node.data && 'fullWidth' in node.data && node.data.fullWidth
7390
? 'max-w-screen-2xl'
74-
: 'page-full-width:ml-0 max-w-3xl',
91+
: 'max-w-3xl',
92+
FULL_WIDTH_BLOCKS.includes(node.type) && 'page-width-wide:max-w-screen-2xl',
7593
blockStyle,
7694
]}
7795
isEstimatedOffscreen={isOffscreen}

packages/gitbook/src/components/DocumentView/Divider.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,5 @@ import type { BlockProps } from './Block';
77
export function Divider(props: BlockProps<DocumentBlockDivider>) {
88
const { style } = props;
99

10-
return <hr className={tcls(style, 'page-full-width:max-w-full border-tint-subtle')} />;
10+
return <hr className={tcls(style, 'page-width-wide:max-w-full border-tint-subtle')} />;
1111
}

packages/gitbook/src/components/DocumentView/Heading.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
2727
'flex',
2828
'items-baseline',
2929
'scroll-m-12',
30+
getTextAlignment(block.data.align),
3031
hashLinkButtonWrapperStyles,
3132
style,
3233
textStyle.marginTop

packages/gitbook/src/components/Footer/Footer.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -36,16 +36,16 @@ export function Footer(props: { context: GitBookSiteContext }) {
3636
<div className={tcls(CONTAINER_STYLE, 'px-4', 'py-8', 'lg:py-12', 'mx-auto')}>
3737
<div
3838
className={tcls(
39-
'lg:!max-w-none mx-auto grid max-w-3xl site-full-width:max-w-screen-2xl justify-between gap-12',
39+
'lg:!max-w-none mx-auto grid max-w-3xl site-width-wide:max-w-screen-2xl justify-between gap-12',
4040
'grid-cols-[auto_auto]',
4141
'lg:grid-cols-[18rem_minmax(auto,_48rem)_auto]',
4242
'xl:grid-cols-[18rem_minmax(auto,_48rem)_14rem]',
43-
'site-full-width:lg:grid-cols-[18rem_minmax(auto,_80rem)_auto]',
44-
'site-full-width:xl:grid-cols-[18rem_minmax(auto,_80rem)_14rem]',
43+
'site-width-wide:lg:grid-cols-[18rem_minmax(auto,_80rem)_auto]',
44+
'site-width-wide:xl:grid-cols-[18rem_minmax(auto,_80rem)_14rem]',
4545
'page-no-toc:lg:grid-cols-[minmax(auto,_48rem)_auto]',
4646
'page-no-toc:xl:grid-cols-[14rem_minmax(auto,_48rem)_14rem]',
47-
'[body:has(.site-full-width,.page-no-toc)_&]:lg:grid-cols-[minmax(auto,_90rem)_auto]',
48-
'[body:has(.site-full-width,.page-no-toc)_&]:xl:grid-cols-[14rem_minmax(auto,_90rem)_14rem]'
47+
'[body:has(.site-width-wide,.page-no-toc)_&]:lg:grid-cols-[minmax(auto,_90rem)_auto]',
48+
'[body:has(.site-width-wide,.page-no-toc)_&]:xl:grid-cols-[14rem_minmax(auto,_90rem)_14rem]'
4949
)}
5050
>
5151
{
@@ -106,7 +106,7 @@ export function Footer(props: { context: GitBookSiteContext }) {
106106
'col-span-2 page-has-toc:lg:col-span-1 page-has-toc:lg:col-start-2 page-no-toc:xl:col-span-1 page-no-toc:xl:col-start-2'
107107
)}
108108
>
109-
<div className="mx-auto flex max-w-3xl site-full-width:max-w-screen-2xl flex-col gap-10 sm:flex-row sm:gap-6">
109+
<div className="mx-auto flex max-w-3xl site-width-wide:max-w-screen-2xl flex-col gap-10 sm:flex-row sm:gap-6">
110110
{partition(customization.footer.groups, FOOTER_COLUMNS).map(
111111
(column, columnIndex) => (
112112
<div

packages/gitbook/src/components/PageAside/PageAside.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export function PageAside(props: {
5555
'chat-open:xl:max-3xl:max-w-0',
5656
'chat-open:xl:max-3xl:ml-0',
5757

58-
'motion-safe:transition-all motion-safe:duration-300',
58+
'motion-safe:xl:transition-all motion-safe:xl:duration-300',
5959
'motion-safe:[transition-behavior:allow-discrete]',
6060

6161
'flex-col',

packages/gitbook/src/components/PageBody/PageBody.tsx

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ export function PageBody(props: {
4040
LINK_PREVIEW_MAX_COUNT
4141
)
4242
: false;
43-
const pageFullWidth = page.id === 'wtthNFMqmEQmnt5LKR0q';
44-
const asFullWidth = pageFullWidth || contentFullWidth;
43+
const pageWidthWide = page.layout.width === 'wide';
44+
const siteWidthWide = pageWidthWide || contentFullWidth;
4545
const language = getSpaceLanguage(customization);
4646
const updatedAt = page.updatedAt ?? page.createdAt;
4747

@@ -53,12 +53,12 @@ export function PageBody(props: {
5353
'mx-auto max-w-screen-2xl py-8',
5454
// Allow words to break if they are too long.
5555
'break-anywhere',
56-
pageFullWidth ? 'page-full-width 2xl:px-8' : 'page-default-width',
57-
asFullWidth ? 'site-full-width' : 'site-default-width',
56+
pageWidthWide ? 'page-width-wide 2xl:px-8' : 'page-width-default',
57+
siteWidthWide ? 'site-width-wide' : 'site-width-default',
5858
page.layout.tableOfContents ? 'page-has-toc' : 'page-no-toc'
5959
)}
6060
>
61-
<PreservePageLayout asFullWidth={asFullWidth} />
61+
<PreservePageLayout siteWidthWide={siteWidthWide} />
6262
{page.cover && page.layout.cover && page.layout.coverSize === 'hero' ? (
6363
<PageCover as="hero" page={page} cover={page.cover} context={context} />
6464
) : null}
@@ -93,19 +93,28 @@ export function PageBody(props: {
9393
<PageFooterNavigation context={context} page={page} />
9494
) : null}
9595

96-
<div className="mx-auto mt-6 page-api-block:ml-0 flex max-w-3xl page-full-width:max-w-screen-2xl flex-row flex-wrap items-center gap-4 text-tint contrast-more:text-tint-strong">
97-
{updatedAt ? (
98-
<p className="mr-auto text-sm">
99-
{t(language, 'page_last_modified', <DateRelative value={updatedAt} />)}
100-
</p>
101-
) : null}
102-
{withPageFeedback ? (
103-
<PageFeedbackForm
104-
className={page.layout.outline ? 'xl:hidden' : ''}
105-
pageId={page.id}
106-
/>
107-
) : null}
108-
</div>
96+
{
97+
// TODO: after 25/07/2025, we can chage it to a true check as the cache will be updated
98+
page.layout.metadata !== false ? (
99+
<div className="mx-auto mt-6 page-api-block:ml-0 flex max-w-3xl page-full-width:max-w-screen-2xl flex-row flex-wrap items-center gap-4 text-tint contrast-more:text-tint-strong">
100+
{updatedAt ? (
101+
<p className="mr-auto text-sm ">
102+
{t(
103+
language,
104+
'page_last_modified',
105+
<DateRelative value={updatedAt} />
106+
)}
107+
</p>
108+
) : null}
109+
{withPageFeedback ? (
110+
<PageFeedbackForm
111+
className={page.layout.outline ? 'xl:hidden' : ''}
112+
pageId={page.id}
113+
/>
114+
) : null}
115+
</div>
116+
) : null
117+
}
109118
</main>
110119

111120
<TrackPageViewEvent />

packages/gitbook/src/components/PageBody/PageBodyBlankslate.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,13 @@ export async function PageBodyBlankslate(props: {
7171
className={tcls(
7272
'grid',
7373
'max-w-3xl',
74+
'page-width-wide:max-w-screen-2xl',
7475
'w-full',
7576
'mx-auto',
7677
'gap-4',
7778
'grid-cols-1',
78-
'sm:grid-cols-2'
79+
'sm:grid-cols-2',
80+
'page-width-wide:md:grid-cols-3'
7981
)}
8082
>
8183
{pageElements}

0 commit comments

Comments
 (0)