Support prominent search bar style (#2936)

Co-authored-by: Nolann Biron <biron.nolann@gmail.com>
This commit is contained in:
Zeno Kapitein
2025-03-14 15:11:21 +01:00
committed by GitHub
parent 99da8df3d1
commit eec3eed100
15 changed files with 134 additions and 62 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Add styling for prominent search bar option
+2 -2
View File
@@ -254,7 +254,7 @@
},
"overrides": {
"@codemirror/state": "6.4.1",
"@gitbook/api": "0.97.0",
"@gitbook/api": "0.99.0",
"react": "18.3.1",
"react-dom": "18.3.1",
},
@@ -627,7 +627,7 @@
"@fortawesome/fontawesome-svg-core": ["@fortawesome/fontawesome-svg-core@6.6.0", "", { "dependencies": { "@fortawesome/fontawesome-common-types": "6.6.0" } }, "sha512-KHwPkCk6oRT4HADE7smhfsKudt9N/9lm6EJ5BVg0tD1yPA5hht837fB87F8pn15D8JfTqQOjhKTktwmLMiD7Kg=="],
"@gitbook/api": ["@gitbook/api@0.97.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-bBTy7nprwlwTW/v8S6A9wGFWatU+F33232xF5Tt4GmSBTZSrAKha5wD205Hr+618va+/zipA8o4hdAGPyUNj0A=="],
"@gitbook/api": ["@gitbook/api@0.99.0", "", { "dependencies": { "event-iterator": "^2.0.0", "eventsource-parser": "^3.0.0" } }, "sha512-qaHNCKul6rp0wqKRQ/2/2+X8mNEmy5ZK4vWuZoI9eL306TTqFBWD4DSTHz0WV6X24FVe3HF7qy/mVRd4ja2I2A=="],
"@gitbook/cache-do": ["@gitbook/cache-do@workspace:packages/cache-do"],
+1 -1
View File
@@ -12,7 +12,7 @@
"@codemirror/state": "6.4.1",
"react": "18.3.1",
"react-dom": "18.3.1",
"@gitbook/api": "0.97.0"
"@gitbook/api": "0.99.0"
},
"private": true,
"scripts": {
+18
View File
@@ -19,6 +19,7 @@ import {
type TestsCase,
allDeprecatedThemePresets,
allLocales,
allSearchStyles,
allSidebarBackgroundStyles,
allThemeModes,
allThemes,
@@ -647,6 +648,23 @@ const testCases: TestsCase[] = [
run: waitForCookiesDialog,
})),
]),
...allSearchStyles.flatMap((searchStyle) => ({
name: `Theme ${theme} Search ${searchStyle} Mode ${themeMode}`,
url: getCustomizationURL({
styling: {
theme,
search: searchStyle,
},
header: {
links: headerLinks,
},
themes: {
default: themeMode,
toggeable: false,
},
}),
run: waitForCookiesDialog,
})),
]),
// Deprecated header themes
...allDeprecatedThemePresets.flatMap((preset) => [
+7
View File
@@ -8,6 +8,7 @@ import {
CustomizationIconsStyle,
CustomizationLinksStyle,
CustomizationLocale,
CustomizationSearchStyle,
CustomizationSidebarBackgroundStyle,
CustomizationSidebarListStyle,
CustomizationTheme,
@@ -109,6 +110,11 @@ export const allSidebarBackgroundStyles: CustomizationSidebarBackgroundStyle[] =
CustomizationSidebarBackgroundStyle.Filled,
];
export const allSearchStyles: CustomizationSearchStyle[] = [
CustomizationSearchStyle.Prominent,
CustomizationSearchStyle.Subtle,
];
// Common customization settings
export const headerLinks: CustomizationHeaderItem[] = [
@@ -257,6 +263,7 @@ export function getCustomizationURL(partial: DeepPartial<SiteCustomizationSettin
background: CustomizationSidebarBackgroundStyle.Default,
list: CustomizationSidebarListStyle.Default,
},
search: CustomizationSearchStyle.Subtle,
},
internationalization: {
locale: CustomizationLocale.En,
@@ -83,6 +83,8 @@ export function Block<T extends DocumentBlock>(props: BlockProps<T>) {
case 'swagger':
case 'openapi-operation':
return <OpenAPI {...props} block={block} />;
case 'openapi-schemas':
return <></>;
case 'embed':
return <Embed {...props} block={block} />;
case 'blockquote':
@@ -156,6 +158,7 @@ export function BlockSkeleton(props: { block: DocumentBlock; style: ClassValue }
case 'table':
case 'swagger':
case 'openapi-operation':
case 'openapi-schemas':
case 'math':
case 'divider':
case 'content-ref':
@@ -16,25 +16,20 @@ export function Footer(props: { context: GitBookSiteContext }) {
const { customization } = context;
return (
<>
<hr className="border-tint-subtle border-t" />
<footer
className={tcls(
'border-tint-subtle border-t',
// If the footer only contains a mode toggle, we only show it on smaller screens
customization.themes.toggeable &&
!customization.footer.copyright &&
!customization.footer.logo &&
customization.footer.groups?.length === 0
? 'xl:hidden'
: null
)}
>
<div className="scroll-nojump">
<footer
className={tcls(
CONTAINER_STYLE,
'px-4',
'mx-auto',
'flex',
'gap-12',
// If the footer only contains a mode toggle, we only show it on smaller screens
customization.themes.toggeable &&
!customization.footer.copyright &&
!customization.footer.logo &&
customization.footer.groups?.length === 0
? 'xl:hidden'
: null
)}
>
<div className={tcls(CONTAINER_STYLE, 'px-4', 'mx-auto', 'flex', 'gap-12')}>
<div className="hidden page-no-toc:hidden basis-72 lg:block" />
<div
className={tcls(
@@ -137,8 +132,8 @@ export function Footer(props: { context: GitBookSiteContext }) {
</div>
</div>
<div className="hidden page-no-toc:hidden lg:block xl:basis-56" />
</footer>
</div>
</div>
</>
</footer>
);
}
@@ -38,6 +38,7 @@ export function Dropdown<E extends HTMLElement>(props: {
aria-orientation="vertical"
aria-labelledby={dropdownId}
className={tcls(
'w-52',
'max-h-80',
'flex',
'absolute',
@@ -55,11 +55,11 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
'theme-bold:shadow-tint-12/2'
)}
>
<div className={tcls('scroll-nojump')}>
<div className="scroll-nojump">
<div
className={tcls(
'gap-4',
'lg:gap-8',
'lg:gap-6',
'flex',
'items-center',
'justify-between',
@@ -72,7 +72,7 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
>
<div
className={tcls(
'flex max-w-full',
'flex max-w-full lg:basis-72',
'min-w-0 shrink items-center justify-start gap-2 lg:gap-4'
)}
>
@@ -90,25 +90,28 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
<HeaderLogo context={context} />
</div>
{customization.header.links.length > 0 && (
<HeaderLinks>
{customization.header.links.map((link, index) => {
return <HeaderLink key={index} link={link} context={context} />;
})}
<HeaderLinkMore
label={t(getSpaceLanguage(customization), 'more')}
links={customization.header.links}
context={context}
/>
</HeaderLinks>
)}
<div
className={tcls(
'flex',
'md:min-w-56',
'grow-0',
'shrink-0',
'justify-self-end'
'md:basis-56',
'justify-self-end',
'search' in customization.styling &&
customization.styling.search === 'prominent'
? [
'md:grow-[0.8]',
'lg:basis-40',
'max-w-lg',
'lg:ml-[max(calc((100%-18rem-48rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - margin (3rem)
'xl:ml-[max(calc((100%-18rem-48rem-14rem-3rem)/2),1.5rem)]', // container (100%) - sidebar (18rem) - content (48rem) - outline (14rem) - margin (3rem)
'page-no-toc:lg:ml-[max(calc((100%-18rem-48rem-18rem-3rem)/2),0rem)]',
'page-full-width:lg:ml-6',
'lg:mr-auto',
'order-last',
'md:order-[unset]',
]
: ['order-last']
)}
>
<Suspense fallback={null}>
@@ -137,6 +140,7 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
'theme-bold:shadow-none',
'theme-bold:hover:shadow-none',
'whitespace-nowrap',
]}
>
<span className={tcls('flex-1')}>
@@ -151,6 +155,25 @@ export function Header(props: { context: GitBookSiteContext; withTopHeader?: boo
</SearchButton>
</Suspense>
</div>
{customization.header.links.length > 0 && (
<HeaderLinks>
{customization.header.links.map((link) => {
return (
<HeaderLink
key={link.title}
link={link}
context={context}
/>
);
})}
<HeaderLinkMore
label={t(getSpaceLanguage(customization), 'more')}
links={customization.header.links}
context={context}
/>
</HeaderLinks>
)}
</div>
</div>
</div>
@@ -34,7 +34,7 @@ export async function HeaderLink(props: {
if (link.links && link.links.length > 0) {
return (
<Dropdown
className="shrink"
className={`shrink ${customization.styling.search === 'prominent' ? 'right-0 left-auto' : null}`}
button={(buttonProps) => {
if (!target || !link.to) {
return (
@@ -151,8 +151,8 @@ function HeaderItemButton(
function getHeaderLinkClassName(_props: { headerPreset: CustomizationHeaderPreset }) {
return tcls(
'flex items-center shrink',
'min-w-0',
'flex items-center',
'shrink',
'contrast-more:underline',
'truncate',
@@ -45,7 +45,13 @@ export function HeaderLinkMore(props: {
return (
<div className={`${styles.linkEllipsis} z-20 items-center`}>
<Dropdown button={renderButton} className="-translate-x-48 md:translate-x-0">
<Dropdown
button={renderButton}
className={tcls(
'max-md:right-0 max-md:left-auto',
context.customization.styling.search === 'prominent' && 'right-0 left-auto'
)}
>
<DropdownMenu>
{links.map((link, index) => (
<MoreMenuLink key={index} link={link} context={context} />
@@ -1,19 +1,21 @@
import type React from 'react';
import { tcls } from '@/lib/tailwind';
import { type ClassValue, tcls } from '@/lib/tailwind';
import styles from './headerLinks.module.css';
interface HeaderLinksProps {
children: React.ReactNode;
style?: ClassValue;
}
export async function HeaderLinks({ children }: HeaderLinksProps) {
export async function HeaderLinks({ children, style }: HeaderLinksProps) {
return (
<div
className={tcls(
styles.containerHeaderlinks,
'lg:[&>.button+.button]:-ml-2 z-20 flex min-w-9 shrink grow items-center justify-end gap-x-4 lg:gap-x-6'
'lg:[&>.button+.button]:-ml-2 z-20 ml-auto flex min-w-9 shrink grow items-center justify-end gap-x-4 lg:gap-x-6 xl:grow-0',
style
)}
>
{children}
@@ -1,6 +1,8 @@
.containerHeaderlinks {
container-type: inline-size;
container-name: headerlinks;
@media (max-width: 1279px) {
.containerHeaderlinks {
container-type: inline-size;
container-name: headerlinks;
}
}
.linkEllipsis {
@@ -43,7 +45,7 @@
}
}
}
@container headerlinks (width < 600px) {
@container headerlinks (width < 550px) {
.containerHeaderlinks > :nth-child(n + 4) {
display: none;
}
@@ -54,7 +56,7 @@
}
}
}
@container headerlinks (width < 750px) {
@container headerlinks (width < 650px) {
.containerHeaderlinks > :nth-child(n + 5) {
display: none;
}
@@ -65,7 +67,7 @@
}
}
}
@container headerlinks (width < 850px) {
@container headerlinks (width < 750px) {
.containerHeaderlinks > :nth-child(n + 6) {
display: none;
}
@@ -43,8 +43,8 @@ export function SearchButton(props: { children?: React.ReactNode; style?: ClassV
'justify-center',
'items-center',
'w-full',
'px-3',
'py-2',
'px-3',
'gap-2',
'bg-tint-base',
@@ -81,10 +81,11 @@ export function SearchButton(props: { children?: React.ReactNode; style?: ClassV
'contrast-more:focus:ring-tint-12',
'active:shadow-sm',
'active:scale-98',
'active:scale-100',
'md:justify-start',
'md:w-full',
'text-sm',
style
)}
>
@@ -99,7 +100,7 @@ export function SearchButton(props: { children?: React.ReactNode; style?: ClassV
}
const Shortcut = () => {
const [operatingSystem, setOperatingSystem] = useState('win');
const [operatingSystem, setOperatingSystem] = useState<string | null>(null);
useEffect(() => {
function getOperatingSystem() {
@@ -114,21 +115,31 @@ const Shortcut = () => {
setOperatingSystem(getOperatingSystem());
}, []);
return (
return operatingSystem ? (
<div
className={tcls(
'shortcut',
'hidden',
'md:inline',
'md:flex',
'gap-0.5',
'-mr-1',
'justify-end',
'text-xs',
'text-tint',
'contrast-more:text-tint-strong',
'whitespace-nowrap',
`[font-feature-settings:"calt",_"case"]`
`[font-feature-settings:"calt",_"case"]`,
'animate-fadeIn'
)}
>
{operatingSystem === 'mac' ? '⌘' : 'Ctrl +'}K
<kbd
className={`flex h-5 min-w-5 items-center justify-center rounded border border-tint-subtle theme-bold:border-header-link/5 bg-tint-base theme-bold:bg-header-background px-1 ${operatingSystem === 'mac' ? 'text-sm' : ''}`}
>
{operatingSystem === 'mac' ? '⌘' : 'Ctrl'}
</kbd>
<kbd className="flex size-5 items-center justify-center rounded border border-tint-subtle theme-bold:border-header-link/5 bg-tint-base theme-bold:bg-header-background">
K
</kbd>
</div>
);
) : null;
};
@@ -6,7 +6,6 @@ import React from 'react';
import { Link } from '@/components/primitives';
import { tcls } from '@/lib/tailwind';
import { SectionIcon } from './SectionIcon';
import type { ClientSiteSection, ClientSiteSections } from './encodeClientSiteSections';