Skip to content

Add fullwidth page option #3344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fuzzy-bulldogs-listen.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gitbook": patch
---

Add fullwidth page option
22 changes: 20 additions & 2 deletions packages/gitbook/src/components/DocumentView/Blocks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,23 @@ type UnwrappedBlocksProps<TBlock extends DocumentBlock> = DocumentContextProps &
isOffscreen?: boolean;
};

/* Blocks that can be full width are automatically expanded on full-width pages.
* Ideally we'd rely on the block type to determine if it can be full width, but
* the block's `fullWidth` property does not differentiate between `undefined` and `false`.
* So instead we hardcode a list of blocks that can be full width. */
Comment on lines +50 to +53
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this comment, why would these blocks differ from others when the page is full-width?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because they automatically grow to expand the size. If we didn't do that, the page option would only affect the page's container, and you would still have to make each block full-width individually.

This way we prevent the option of having a wide page with a lot of space on the right, because any fullwidth block (tabs, tables, ...) grows automatically.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is still very confusing, and smells very bad that we have an hardcoded set of block types...

I don't have time to deep dive, but yeah it smells fishy

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the following mean?

the block's fullWidth property does not differentiate between undefined and false.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it's far from perfect and I am very open to better approaches.

What does the following mean?

the block's fullWidth property does not differentiate between undefined and false.

I need to set a block's max width based on if its fullWidth prop:

  • fullWidth=undefined: the block cannot expand, so it should always stay narrow.
  • fullWidth=false: the block can expand, but is not set to expand by the user. By default we do nothing. On wide pages, we should automatically expand it so the user doesn't have to toggle it manually on every single block.
  • fulLWidth=true: the block is set to expand by the user. We need to expand it.

The problem is this: the API only returns undefined and true. If a block is set to expand, the fullWidth prop is removed entirely instead of being set to false, even though it's an optional boolean so can be true|false|undefined.

This means I cannot know on the front-end if I need to show a block narrow (because blocks without fullWidth should remain narrow) or expand it (because blocks with fullWidth=true and fullWidth=false should expand).

Two solutions I see:

  1. There's probably a non-strict falsy check somewhere that is removing fullWidth instead of setting it to false deliberately. If we change that I can read out all three states and remove this hardcoded array.
  2. We can explicitly save each block as fullWidth=true when the page is set to wide layout. This way the front-end can just expand whatever block on which fullWidth exists, and keep the rest narrow. But we're then actually editing blocks' markup based on the page they're in, that feels strange.

I think 1 is the easiest solution. But I'm also very open to other ideas I haven't thought of yet.
cc @BrettJephson

const FULL_WIDTH_BLOCKS = [
'table',
'tabs',
'integration',
'openapi',
'images',
'embed',
'columns',
'code',
'content-ref',
'hint',
];

/**
* Renders a list of blocks without a wrapper element.
*/
Expand All @@ -68,10 +85,11 @@ export function UnwrappedBlocks<TBlock extends DocumentBlock>(props: UnwrappedBl
key={node.key || `${node.type}-${index}`}
block={node}
style={[
'mx-auto w-full decoration-primary/6',
'mx-auto page-width-wide:mx-0 w-full decoration-primary/6',
node.data && 'fullWidth' in node.data && node.data.fullWidth
? 'max-w-screen-2xl'
: 'page-full-width:ml-0 max-w-3xl',
: 'max-w-3xl',
FULL_WIDTH_BLOCKS.includes(node.type) && 'page-width-wide:max-w-screen-2xl',
blockStyle,
]}
isEstimatedOffscreen={isOffscreen}
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/DocumentView/Divider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ import type { BlockProps } from './Block';
export function Divider(props: BlockProps<DocumentBlockDivider>) {
const { style } = props;

return <hr className={tcls(style, 'page-full-width:max-w-full border-tint-subtle')} />;
return <hr className={tcls(style, 'page-width-wide:max-w-full border-tint-subtle')} />;
}
1 change: 1 addition & 0 deletions packages/gitbook/src/components/DocumentView/Heading.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function Heading(props: BlockProps<DocumentBlockHeading>) {
'heading',
'grid',
'scroll-m-12',
getTextAlignment(block.data.align),
hashLinkButtonWrapperStyles,
style
)}
Expand Down
12 changes: 6 additions & 6 deletions packages/gitbook/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ export function Footer(props: { context: GitBookSiteContext }) {
<div className={tcls(CONTAINER_STYLE, 'px-4', 'py-8', 'lg:py-12', 'mx-auto')}>
<div
className={tcls(
'lg:!max-w-none mx-auto grid max-w-3xl site-full-width:max-w-screen-2xl justify-between gap-12',
'lg:!max-w-none mx-auto grid max-w-3xl site-width-wide:max-w-screen-2xl justify-between gap-12',
'grid-cols-[auto_auto]',
'lg:grid-cols-[18rem_minmax(auto,_48rem)_auto]',
'xl:grid-cols-[18rem_minmax(auto,_48rem)_14rem]',
'site-full-width:lg:grid-cols-[18rem_minmax(auto,_80rem)_auto]',
'site-full-width:xl:grid-cols-[18rem_minmax(auto,_80rem)_14rem]',
'site-width-wide:lg:grid-cols-[18rem_minmax(auto,_80rem)_auto]',
'site-width-wide:xl:grid-cols-[18rem_minmax(auto,_80rem)_14rem]',
'page-no-toc:lg:grid-cols-[minmax(auto,_48rem)_auto]',
'page-no-toc:xl:grid-cols-[14rem_minmax(auto,_48rem)_14rem]',
'[body:has(.site-full-width,.page-no-toc)_&]:lg:grid-cols-[minmax(auto,_90rem)_auto]',
'[body:has(.site-full-width,.page-no-toc)_&]:xl:grid-cols-[14rem_minmax(auto,_90rem)_14rem]'
'[body:has(.site-width-wide,.page-no-toc)_&]:lg:grid-cols-[minmax(auto,_90rem)_auto]',
'[body:has(.site-width-wide,.page-no-toc)_&]:xl:grid-cols-[14rem_minmax(auto,_90rem)_14rem]'
)}
>
{
Expand Down Expand Up @@ -106,7 +106,7 @@ export function Footer(props: { context: GitBookSiteContext }) {
'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'
)}
>
<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">
<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">
{partition(customization.footer.groups, FOOTER_COLUMNS).map(
(column, columnIndex) => (
<div
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/PageAside/PageAside.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function PageAside(props: {
'chat-open:xl:max-3xl:max-w-0',
'chat-open:xl:max-3xl:ml-0',

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

'flex-col',
Expand Down
10 changes: 5 additions & 5 deletions packages/gitbook/src/components/PageBody/PageBody.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export function PageBody(props: {
LINK_PREVIEW_MAX_COUNT
)
: false;
const pageFullWidth = page.id === 'wtthNFMqmEQmnt5LKR0q';
const asFullWidth = pageFullWidth || contentFullWidth;
const pageWidthWide = page.layout.width === 'wide';
const siteWidthWide = pageWidthWide || contentFullWidth;
const language = getSpaceLanguage(customization);
const updatedAt = page.updatedAt ?? page.createdAt;

Expand All @@ -53,12 +53,12 @@ export function PageBody(props: {
'mx-auto max-w-screen-2xl py-8',
// Allow words to break if they are too long.
'break-anywhere',
pageFullWidth ? 'page-full-width 2xl:px-8' : 'page-default-width',
asFullWidth ? 'site-full-width' : 'site-default-width',
pageWidthWide ? 'page-width-wide 2xl:px-8' : 'page-width-default',
siteWidthWide ? 'site-width-wide' : 'site-width-default',
page.layout.tableOfContents ? 'page-has-toc' : 'page-no-toc'
)}
>
<PreservePageLayout asFullWidth={asFullWidth} />
<PreservePageLayout siteWidthWide={siteWidthWide} />
{page.cover && page.layout.cover && page.layout.coverSize === 'hero' ? (
<PageCover as="hero" page={page} cover={page.cover} context={context} />
) : null}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,11 +71,13 @@ export async function PageBodyBlankslate(props: {
className={tcls(
'grid',
'max-w-3xl',
'page-width-wide:max-w-screen-2xl',
'w-full',
'mx-auto',
'gap-4',
'grid-cols-1',
'sm:grid-cols-2'
'sm:grid-cols-2',
'page-width-wide:md:grid-cols-3'
)}
>
{pageElements}
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/PageBody/PageCover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ export async function PageCover(props: {
: [
'sm:mx-auto',
'max-w-3xl ',
'page-full-width:max-w-screen-2xl',
'page-width-wide:max-w-screen-2xl',
'sm:rounded-md',
'mb-8',
]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export async function PageFooterNavigation(props: {
'mt-6',
'gap-2',
'max-w-3xl',
'page-full-width:max-w-screen-2xl',
'page-width-wide:max-w-screen-2xl',
'mx-auto',
'text-tint'
)}
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/PageBody/PageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function PageHeader(props: {
<header
className={tcls(
'max-w-3xl',
'page-full-width:max-w-screen-2xl',
'page-width-wide:max-w-screen-2xl',
'mx-auto',
'mb-6',
'space-y-3',
Expand Down
18 changes: 9 additions & 9 deletions packages/gitbook/src/components/PageBody/PreservePageLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ import * as React from 'react';
* This approach is needed as page layout (full width block) is done using CSS (`body:has(.full-width)`),
* which becomes false while transitioning between the 2 page states:
*
* 1. Page 1 with full width block: `body:has(.site-full-width)` is true
* 2. Loading skeleton while transitioning to page 2: `body:has(.site-full-width)` is false
* 3. Page 2 with full width block: `body:has(.site-full-width)` is true
* 1. Page 1 with full width block: `body:has(.site-width-wide)` is true
* 2. Loading skeleton while transitioning to page 2: `body:has(.site-width-wide)` is false
* 3. Page 2 with full width block: `body:has(.site-width-wide)` is true
*
* This component ensures that the layout is preserved while transitioning between the 2 page states (in step 2).
*/
export function PreservePageLayout(props: { asFullWidth: boolean }) {
const { asFullWidth } = props;
export function PreservePageLayout(props: { siteWidthWide: boolean }) {
const { siteWidthWide } = props;

React.useLayoutEffect(() => {
// We use the header as it's an element preserved between page transitions
Expand All @@ -23,12 +23,12 @@ export function PreservePageLayout(props: { asFullWidth: boolean }) {
return;
}

if (asFullWidth) {
header.classList.add('site-full-width');
if (siteWidthWide) {
header.classList.add('site-width-wide');
} else {
header.classList.remove('site-full-width');
header.classList.remove('site-width-wide');
}
}, [asFullWidth]);
}, [siteWidthWide]);

return null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function SitePageSkeleton() {
'lg:items-start'
)}
>
<div className={tcls('flex-1', 'max-w-3xl', 'mx-auto', 'site-full-width:mx-0')}>
<div className={tcls('flex-1', 'max-w-3xl', 'mx-auto', 'site-width-wide:mx-0')}>
<SkeletonHeading style={tcls('mb-8')} />
<SkeletonParagraph style={tcls('mb-4')} />
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export function SpaceLayout(props: {
'flex-col',
'lg:flex-row',
CONTAINER_STYLE,
'site-full-width:max-w-full',
'site-width-wide:max-w-full',

// Ensure the footer is display below the viewport even if the content is not enough
withFooter && 'min-h-[calc(100vh-64px)]',
Expand Down
1 change: 0 additions & 1 deletion packages/gitbook/src/components/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ export const CONTAINER_STYLE: ClassValue = [
'md:px-8',
'max-w-screen-2xl',
'mx-auto',
// 'site-full-width:max-w-full',
];

/**
Expand Down
6 changes: 3 additions & 3 deletions packages/gitbook/tailwind.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -560,9 +560,9 @@ const config: Config = {
/**
* Variant when the page contains a block that will be rendered in full-width mode.
*/
addVariant('site-full-width', 'body:has(.site-full-width) &');
addVariant('site-default-width', 'body:has(.site-default-width) &');
addVariant('page-full-width', 'body:has(.page-full-width) &');
addVariant('site-width-wide', 'body:has(.site-width-wide) &');
addVariant('site-width-default', 'body:has(.site-width-default) &');
addVariant('page-width-wide', 'body:has(.page-width-wide) &');

/**
* Variant when the page is configured to hide the table of content.
Expand Down