diff --git a/packages/gitbook/src/components/Header/HeaderLogo.tsx b/packages/gitbook/src/components/Header/HeaderLogo.tsx
index c553b8178..62c3f6025 100644
--- a/packages/gitbook/src/components/Header/HeaderLogo.tsx
+++ b/packages/gitbook/src/components/Header/HeaderLogo.tsx
@@ -1,11 +1,16 @@
import type { GitBookSiteContext } from '@/lib/context';
import { Image } from '@/components/utils';
-import { tcls } from '@/lib/tailwind';
import { resolveContentRef } from '@/lib/references';
import { Link } from '../primitives';
import { CurrentContentIcon } from './CurrentContentIcon';
+import {
+ HEADER_LOGO_CONTAINER_CLASS,
+ HEADER_LOGO_IMAGE_CLASS,
+ HEADER_LOGO_IMAGE_SIZES,
+ HeaderLogoContent,
+} from './HeaderLogoContent';
interface HeaderLogoProps {
context: GitBookSiteContext;
@@ -26,83 +31,56 @@ export async function HeaderLogo(props: HeaderLogoProps) {
return (
- {customization.header.logo ? (
-
- ) : (
-
- )}
+ : null}
+ fallbackIcon={}
+ title={context.site.title}
+ />
);
}
-function LogoFallback(props: HeaderLogoProps) {
+function LogoImage(props: HeaderLogoProps) {
const { context } = props;
- const { site } = context;
+ const { customization } = context;
+
+ if (!customization.header.logo) {
+ return null;
+ }
return (
- <>
-
-
- {site.title}
-
- >
+
+ );
+}
+
+function LogoFallbackIcon(props: HeaderLogoProps) {
+ const { context } = props;
+
+ return (
+
);
}
diff --git a/packages/gitbook/src/components/Header/HeaderLogoContent.tsx b/packages/gitbook/src/components/Header/HeaderLogoContent.tsx
new file mode 100644
index 000000000..c2a6c8e06
--- /dev/null
+++ b/packages/gitbook/src/components/Header/HeaderLogoContent.tsx
@@ -0,0 +1,78 @@
+import type { ReactNode } from 'react';
+
+import { tcls } from '@/lib/tailwind';
+
+export const HEADER_LOGO_IMAGE_SIZES = [
+ {
+ media: '(max-width: 1024px)',
+ width: 160,
+ },
+ {
+ width: 260,
+ },
+];
+
+export const HEADER_LOGO_CONTAINER_CLASS = tcls(
+ 'group/headerlogo',
+ 'min-w-0',
+ 'shrink',
+ 'flex',
+ 'items-center'
+);
+
+export const HEADER_LOGO_IMAGE_CLASS = tcls(
+ 'overflow-hidden',
+ 'shrink',
+ 'min-w-0',
+ 'max-w-40',
+ 'lg:max-w-64',
+ 'lg:site-header-none:page-no-toc:max-w-56',
+ 'max-h-8',
+ 'h-full',
+ 'w-full',
+ 'object-contain',
+ 'object-left'
+);
+
+interface HeaderLogoContentProps {
+ logo: ReactNode | null;
+ fallbackIcon: ReactNode;
+ title: ReactNode;
+}
+
+export function HeaderLogoContent(props: HeaderLogoContentProps) {
+ const { logo, fallbackIcon, title } = props;
+
+ if (logo) {
+ return logo;
+ }
+
+ return (
+ <>
+ {fallbackIcon}
+ {title}
+ >
+ );
+}
+
+function HeaderLogoTitle(props: { children: ReactNode }) {
+ return (
+
+ {props.children}
+
+ );
+}
diff --git a/packages/gitbook/src/components/StructurePreview/StructurePreview.tsx b/packages/gitbook/src/components/StructurePreview/StructurePreview.tsx
index fd989ac96..cb51ad50a 100644
--- a/packages/gitbook/src/components/StructurePreview/StructurePreview.tsx
+++ b/packages/gitbook/src/components/StructurePreview/StructurePreview.tsx
@@ -10,6 +10,11 @@ import { getLocalizedTitle } from '@/lib/sites';
import { tcls } from '@/lib/tailwind';
import { tString, useLanguage } from '@/intl/client';
+import {
+ HEADER_LOGO_CONTAINER_CLASS,
+ HEADER_LOGO_IMAGE_CLASS,
+ HeaderLogoContent,
+} from '../Header/HeaderLogoContent';
import headerLinksStyles from '../Header/headerLinks.module.css';
import { CONTAINER_STYLE, HEADER_HEIGHT_DESKTOP } from '../layout';
import { Button, ToggleChevron } from '../primitives';
@@ -255,72 +260,49 @@ function StructurePreviewLogo(props: { snapshot: StructurePreviewSnapshot }) {
const { customization } = snapshot;
return (
-
- {customization.header.logo ? (
-
- {customization.header.logo.dark ? (
-
- ) : null}
-
-
- ) : (
- <>
- {'emoji' in customization.favicon && customization.favicon.emoji ? (
-
{customization.favicon.emoji}
- ) : (
-
-
-
-
- )}
-
- {snapshot.site.title}
-
- >
- )}
+
+
+ ) : null
+ }
+ fallbackIcon={}
+ title={snapshot.site.title}
+ />
);
}
+function StructurePreviewLogoImage(props: {
+ logo: NonNullable
;
+}) {
+ const { logo } = props;
+
+ return (
+
+ {logo.dark ? : null}
+
+
+ );
+}
+
+function StructurePreviewLogoFallbackIcon(props: { snapshot: StructurePreviewSnapshot }) {
+ const { snapshot } = props;
+ const { customization } = snapshot;
+
+ if ('emoji' in customization.favicon && customization.favicon.emoji) {
+ return {customization.favicon.emoji};
+ }
+
+ return (
+
+
+
+
+ );
+}
+
function StructurePreviewSearch(props: { style: CustomizationSearchStyle }) {
const language = useLanguage();
const label = tString(language, 'search');