Skip to content
Merged
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/sour-cobras-grab.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"gitbook": minor
---

Update site layout and blocks with container queries and better transitions
14 changes: 8 additions & 6 deletions packages/gitbook/src/components/AIChat/AIChat.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { t, tString, useLanguage } from '@/intl/client';
import type { TranslationLanguage } from '@/intl/translations';
import { tcls } from '@/lib/tailwind';
import { Icon } from '@gitbook/icons';
import React from 'react';
import { useHotkeys } from 'react-hotkeys-hook';
Expand Down Expand Up @@ -65,16 +66,17 @@ export function AIChat(props: { trademark: boolean }) {
}
}, [chat.opened, trackEvent]);

if (!chat.opened) {
return null;
}

return (
<div
data-testid="ai-chat"
className="ai-chat inset-y-0 right-0 z-40 mx-auto flex max-w-3xl animate-present scroll-mt-36 px-4 py-4 transition-all duration-300 sm:px-6 lg:fixed lg:w-80 lg:animate-enter-from-right lg:pr-4 lg:pl-0 xl:w-96"
className={tcls(
'ai-chat inset-y-0 right-0 z-40 mx-auto flex max-w-3xl scroll-mt-36 px-4 py-4 transition-[width,opacity,margin,display] transition-discrete duration-300 sm:px-6 lg:fixed lg:w-80 lg:pr-4 lg:pl-0 xl:w-96',
chat.opened
? 'lg:starting:ml-0 lg:starting:w-0 lg:starting:opacity-0'
: 'hidden lg:ml-0 lg:w-0! lg:opacity-0'
)}
>
<EmbeddableFrame className="relative circular-corners:rounded-3xl rounded-corners:rounded-md depth-subtle:shadow-lg shadow-tint ring-1 ring-tint-subtle">
<EmbeddableFrame className="relative shrink-0 circular-corners:rounded-3xl rounded-corners:rounded-md border border-tint-subtle depth-subtle:shadow-lg shadow-tint transition-all duration-300 lg:w-76 xl:w-92">
<EmbeddableFrameHeader>
<AIChatDynamicIcon trademark={trademark} />
<EmbeddableFrameHeaderMain>
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/AIChat/AIChatButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export function AIChatButton(props: {
iconOnly={!showLabel}
size="medium"
variant="header"
className="h-9 px-2.5 max-md:[&_.button-content]:hidden"
className="h-9 px-2.5 @max-2xl:[&_.button-content]:hidden"
label={
<div className="flex items-center gap-2">
{t(language, 'ai_chat_ask', assistant.label)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export function Column(props: {
<div
className={tcls(
'flex flex-col',
'@container/column',
(verticalAlignment === VerticalAlignment.Top || !verticalAlignment) &&
'justify-start',
verticalAlignment === VerticalAlignment.Middle && 'justify-center',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export async function RecordCard(
'overflow-hidden',
'[&_.heading>div:first-child]:hidden',
'[&_.heading>div]:text-[.8em]',
'md:[&_.heading>div]:text-[1em]',
'@xl:[&_.heading>div]:text-[1em]',
'[&_.blocks:first-child_.heading]:pt-0', // Remove padding-top on first heading in card

// On mobile, check if we can display the cover responsively or not:
Expand All @@ -69,10 +69,10 @@ export async function RecordCard(
lightCoverIsSquareOrPortrait || darkCoverIsSquareOrPortrait
? [
lightCoverIsSquareOrPortrait
? 'grid-cols-[40%__1fr] min-[432px]:grid-cols-none min-[432px]:grid-rows-[auto_1fr]'
? '@sm:grid-cols-none grid-cols-[40%__1fr] @sm:grid-rows-[auto_1fr]'
: '',
darkCoverIsSquareOrPortrait
? 'dark:grid-cols-[40%__1fr] dark:min-[432px]:grid-cols-none dark:min-[432px]:grid-rows-[auto_1fr]'
? 'dark:@sm:grid-cols-none dark:grid-cols-[40%__1fr] dark:@sm:grid-rows-[auto_1fr]'
: '',
].filter(Boolean)
: 'grid-rows-[auto_1fr]'
Expand Down Expand Up @@ -112,11 +112,9 @@ export async function RecordCard(
'bg-tint-subtle',
lightCoverIsSquareOrPortrait || darkCoverIsSquareOrPortrait
? [
lightCoverIsSquareOrPortrait
? 'min-[432px]:aspect-video min-[432px]:h-auto'
: '',
lightCoverIsSquareOrPortrait ? '@sm:aspect-video @sm:h-auto' : '',
darkCoverIsSquareOrPortrait
? 'dark:min-[432px]:aspect-video dark:min-[432px]:h-auto'
? 'dark:@sm:aspect-video dark:@sm:h-auto'
: '',
].filter(Boolean)
: ['h-auto', 'aspect-video'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ export function ViewCards(props: TableViewProps<DocumentTableViewCards>) {
'inline-grid',
'gap-4',
'grid-cols-1',
'min-[432px]:grid-cols-2',
view.cardSize === 'large' ? 'md:grid-cols-2' : 'md:grid-cols-3',
'@sm:grid-cols-2',
view.cardSize === 'large' ? '@xl:grid-cols-2' : '@xl:grid-cols-3',
block.data.fullWidth ? 'large:flex-column' : null
)}
>
Expand Down
6 changes: 3 additions & 3 deletions packages/gitbook/src/components/DocumentView/spacing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,19 @@ export function getBlockTextStyle(block: DocumentBlock): {
};
case 'heading-1':
return {
textSize: 'text-3xl font-semibold',
textSize: 'text-xl @xs:text-2xl @lg:text-3xl font-semibold',
lineHeight: 'leading-tight',
marginTop: 'column-first-of-type:pt-0 pt-[1em]',
};
case 'heading-2':
return {
textSize: 'text-2xl font-semibold',
textSize: 'text-lg @xs:text-xl @lg:text-2xl font-semibold',
lineHeight: 'leading-snug',
marginTop: 'column-first-of-type:pt-0 pt-[0.75em]',
};
case 'heading-3':
return {
textSize: 'text-xl font-semibold',
textSize: 'text-base @xs:text-lg @lg:text-xl font-semibold',
lineHeight: 'leading-snug',
marginTop: 'column-first-of-type:pt-0 pt-[0.5em]',
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export const EmbeddableFrame = React.forwardRef<HTMLDivElement, EmbeddableFrameP
<div
{...divProps}
className={tcls(
'flex h-full grow animate-fade-in-slow flex-col overflow-hidden bg-tint-base text-sm text-tint',
'flex h-full grow flex-col overflow-hidden bg-tint-base text-sm text-tint',
divProps.className
)}
ref={ref}
Expand Down
201 changes: 106 additions & 95 deletions packages/gitbook/src/components/Footer/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,112 +29,123 @@ export function Footer(props: { context: GitBookSiteContext }) {
className={tcls(
'border-tint-subtle border-t',
// If the footer only contains a mode toggle, we only show it on smaller screens
mobileOnly ? 'xl:hidden' : null
mobileOnly ? '@7xl:hidden' : null
)}
>
<div className={tcls(CONTAINER_STYLE, 'px-4', 'py-8', 'lg:py-12', 'mx-auto')}>
<div className="motion-safe:transition-[padding] motion-safe:duration-300 lg:chat-open:pr-80 xl:chat-open:pr-96">
<div
className={tcls(
'mx-auto grid max-w-3xl site-width-wide:max-w-screen-2xl justify-between gap-12 lg:max-w-none!',
'grid-cols-[auto_auto]',
'lg:grid-cols-[18rem_minmax(auto,48rem)_auto]',
'xl:grid-cols-[18rem_minmax(auto,48rem)_14rem]',
'lg:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_auto]',
'xl:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_14rem]',
'lg:page-no-toc:grid-cols-[minmax(auto,48rem)_auto]',
'xl:page-no-toc:grid-cols-[14rem_minmax(auto,48rem)_14rem]',
'lg:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[minmax(auto,90rem)_auto]',
'xl:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[14rem_minmax(auto,90rem)_14rem]'
CONTAINER_STYLE,
'px-4',
'py-8',
'@4xl:py-12',
'mx-auto',
'@container/footer'
)}
>
{
// Footer Logo
customization.footer.logo ? (
<div className="col-start-1 row-start-1">
<Image
alt="Logo"
resize={context.imageResizer}
sources={{
light: {
src: customization.footer.logo.light,
},
dark: customization.footer.logo.dark
? {
src: customization.footer.logo.dark,
}
: null,
}}
loading="lazy"
style={[
'w-auto',
'max-w-40',
'lg:max-w-64',
'max-h-10',
'lg:max-h-12',
'object-contain',
'object-left',
'rounded-sm',
'straight-corners:rounded-xs',
]}
sizes={[
{
width: 320,
},
]}
/>
</div>
) : null
}
<div
className={tcls(
'mx-auto flex @xs:grid @4xl:max-w-none! max-w-3xl site-width-wide:max-w-screen-2xl flex-col justify-between gap-12',
'grid-cols-[auto_auto]',
'@4xl:grid-cols-[18rem_minmax(auto,48rem)_auto]',
'@7xl:grid-cols-[18rem_minmax(auto,48rem)_14rem]',
'@4xl:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_auto]',
'@7xl:site-width-wide:grid-cols-[18rem_minmax(auto,80rem)_14rem]',
'@4xl:page-no-toc:grid-cols-[minmax(auto,48rem)_auto]',
'@7xl:page-no-toc:grid-cols-[14rem_minmax(auto,48rem)_14rem]',
'@4xl:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[minmax(auto,90rem)_auto]',
'@7xl:[body:has(.site-width-wide,.page-no-toc)_&]:grid-cols-[14rem_minmax(auto,90rem)_14rem]'
)}
>
{
// Footer Logo
customization.footer.logo ? (
<div className="col-start-1 row-start-1">
<Image
alt="Logo"
resize={context.imageResizer}
sources={{
light: {
src: customization.footer.logo.light,
},
dark: customization.footer.logo.dark
? {
src: customization.footer.logo.dark,
}
: null,
}}
loading="lazy"
style={[
'w-auto',
'max-w-40',
'@4xl:max-w-64',
'max-h-10',
'@4xl:max-h-12',
'object-contain',
'object-left',
'rounded-sm',
'straight-corners:rounded-xs',
]}
sizes={[
{
width: 320,
},
]}
/>
</div>
) : null
}

{
// Theme Toggle
customization.themes.toggeable ? (
<div className="-col-start-2 row-start-1 flex items-start justify-end xl:hidden">
<React.Suspense fallback={null}>
<ThemeToggler />
</React.Suspense>
</div>
) : null
}
{
// Theme Toggle
customization.themes.toggeable ? (
<div className="-col-start-2 row-start-1 flex items-start @xs:justify-end xl:hidden">
<React.Suspense fallback={null}>
<ThemeToggler />
</React.Suspense>
</div>
) : null
}

{
// Navigation groups (split into equal columns)
customization.footer.groups?.length > 0 ? (
<div
className={tcls(
'col-span-2 lg:page-has-toc:col-span-1 lg:page-has-toc:col-start-2 xl:page-no-toc:col-span-1 xl:page-no-toc:col-start-2'
)}
>
<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
key={columnIndex}
className="flex flex-1 grow flex-col gap-10"
>
{column.map((group, groupIndex) => (
<FooterLinksGroup
key={groupIndex}
group={group}
context={context}
/>
))}
</div>
)
{
// Navigation groups (split into equal columns)
customization.footer.groups?.length > 0 ? (
<div
className={tcls(
'@4xl:page-has-toc:col-span-1 @7xl:page-no-toc:col-span-1 col-span-2 @4xl:page-has-toc:col-start-2 @7xl:page-no-toc:col-start-2'
)}
>
<div className="mx-auto flex max-w-3xl site-width-wide:max-w-screen-2xl @xl:flex-row flex-col @xl:gap-6 gap-10">
{partition(customization.footer.groups, FOOTER_COLUMNS).map(
(column, columnIndex) => (
<div
key={columnIndex}
className="flex flex-1 grow flex-col gap-10"
>
{column.map((group, groupIndex) => (
<FooterLinksGroup
key={groupIndex}
group={group}
context={context}
/>
))}
</div>
)
)}
</div>
</div>
</div>
) : null
}
) : null
}

{
// Legal
customization.footer.copyright ? (
<div className="order-last col-span-full flex w-full grow flex-col items-center gap-2 text-center text-tint text-xs">
<p>{customization.footer.copyright}</p>
</div>
) : null
}
{
// Legal
customization.footer.copyright ? (
<div className="order-last col-span-full flex w-full grow flex-col items-center gap-2 text-center text-tint text-xs">
<p>{customization.footer.copyright}</p>
</div>
) : null
}
</div>
</div>
</div>
</footer>
Expand Down
Loading
Loading