Skip to content

Commit

Permalink
Update header styling (#2613)
Browse files Browse the repository at this point in the history
Co-authored-by: Valentino Hudhra <v.hudhra@gmail.com>
Co-authored-by: Valentino Hudhra <2587839+valentin0h@users.noreply.github.com>
  • Loading branch information
3 people authored Dec 13, 2024
1 parent 2f76712 commit 23584c9
Show file tree
Hide file tree
Showing 18 changed files with 411 additions and 305 deletions.
5 changes: 5 additions & 0 deletions .changeset/curly-phones-judge.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'gitbook': patch
---

Update the site header with new styling, a new search button, and refactored layout
26 changes: 15 additions & 11 deletions packages/gitbook/e2e/pages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ const testCases: TestsCase[] = [
name: 'Variants dropdown',
url: '',
run: async (page) => {
const spaceDrowpdown = page.locator('[data-testid="space-dropdown-button"]');
const spaceDrowpdown = page
.locator('[data-testid="space-dropdown-button"]')
.locator('visible=true');
await spaceDrowpdown.waitFor();
},
},
Expand All @@ -128,7 +130,9 @@ const testCases: TestsCase[] = [
name: 'Customized variant titles are displayed',
url: '',
run: async (page) => {
const spaceDrowpdown = page.locator('[data-testid="space-dropdown-button"]');
const spaceDrowpdown = page
.locator('[data-testid="space-dropdown-button"]')
.locator('visible=true');
await spaceDrowpdown.click();

const variantSelectionDropdown = page.locator(
Expand Down Expand Up @@ -160,9 +164,9 @@ const testCases: TestsCase[] = [
url: 'api-multi-versions/reference/api-reference/pets',
screenshot: false,
run: async (page) => {
const spaceDrowpdown = await page.waitForSelector(
'[data-testid="space-dropdown-button"]',
);
const spaceDrowpdown = await page
.locator('[data-testid="space-dropdown-button"]')
.locator('visible=true');
await spaceDrowpdown.click();

// Click the second variant in the dropdown
Expand All @@ -183,9 +187,9 @@ const testCases: TestsCase[] = [
url: 'api-multi-versions-share-links/8tNo6MeXg7CkFMzSSz81/reference/api-reference/pets',
screenshot: false,
run: async (page) => {
const spaceDrowpdown = await page.waitForSelector(
'[data-testid="space-dropdown-button"]',
);
const spaceDrowpdown = await page
.locator('[data-testid="space-dropdown-button"]')
.locator('visible=true');
await spaceDrowpdown.click();

// Click the second variant in the dropdown
Expand Down Expand Up @@ -218,9 +222,9 @@ const testCases: TestsCase[] = [
return `api-multi-versions-va/reference/api-reference/pets?jwt_token=${token}`;
})(),
run: async (page) => {
const spaceDrowpdown = await page.waitForSelector(
'[data-testid="space-dropdown-button"]',
);
const spaceDrowpdown = await page
.locator('[data-testid="space-dropdown-button"]')
.locator('visible=true');
await spaceDrowpdown.click();

// Click the second variant in the dropdown
Expand Down
2 changes: 1 addition & 1 deletion packages/gitbook/src/components/Header/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function Dropdown<E extends HTMLElement>(props: {
const dropdownId = useId();

return (
<div className={tcls('group/dropdown', 'relative flex')}>
<div className={tcls('group/dropdown', 'relative flex shrink min-w-0')}>
{button({
id: dropdownId,
tabIndex: 0,
Expand Down
221 changes: 137 additions & 84 deletions packages/gitbook/src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { HeaderLogo } from './HeaderLogo';
import { SpacesDropdown } from './SpacesDropdown';
import { SearchButton } from '../Search';
import { SiteSectionTabs } from '../SiteSectionTabs';
import { HeaderMobileMenu } from './HeaderMobileMenu';
/**
* Render the header for the space.
*/
Expand Down Expand Up @@ -45,104 +46,156 @@ export function Header(props: {
'w-full',
'flex-none',
'shadow-thinbottom',
'dark:shadow-light/2',
'bg-light',
'dark:bg-dark',
withTopHeader ? null : 'lg:hidden',
'lg:z-10',
'dark:shadow-light/1',
`${isCustomizationDefault || !withTopHeader ? 'bg-light' : 'bg-header-background'}`,
`${
isCustomizationDefault || !withTopHeader
? 'dark:bg-dark'
: 'bg-header-background'
}`,
'text-sm',
'bg-opacity-9',
'dark:bg-opacity-9',
'backdrop-blur-lg',
'contrast-more:bg-opacity-11',
'contrast-more:dark:bg-opacity-11',
)}
>
<div className={tcls('scroll-nojump')}>
<div
className={tcls(
'gap-4',
'grid',
'grid-flow-col',
'auto-cols-[auto_auto_1fr_auto]',
'h-16',
'items-center',
'align-center',
'justify-between',
'w-full',
CONTAINER_STYLE,
)}
>
<HeaderLogo site={site} space={space} customization={customization} />
<div className="z-20">
{!hasSiteSections && isMultiVariants ? (
<SpacesDropdown space={space} spaces={spaces} />
) : null}
</div>
<HeaderLinks>
{customization.header.links.map((link, index) => {
return (
<HeaderLink
key={index}
link={link}
context={context}
customization={customization}
/>
);
})}
<HeaderLinkMore
label={t(getSpaceLanguage(customization), 'more')}
links={customization.header.links}
context={context}
customization={customization}
/>
</HeaderLinks>
<div
className={tcls(
!isCustomizationDefault &&
withTopHeader && [
'bg-header-background',
'shadow-thinbottom',
'dark:shadow-light/2',
],
)}
>
<div className={tcls('scroll-nojump')}>
<div
className={tcls(
'gap-4',
'lg:gap-8',
'flex',
'md:w-56',
'grow-0',
'shrink-0',
'justify-self-end',
'h-16',
'items-center',
'justify-between',
'w-full',
CONTAINER_STYLE,
)}
>
<Suspense fallback={null}>
<SearchButton
style={
!isCustomizationDefault && withTopHeader
? [
'bg-header-link/3',
'shadow-sm',
'ring-header-link/3',
'[&>span]:!text-header-link/7',
'[&_svg]:text-header-link',
'contrast-more:bg-transparent',
'contrast-more:ring-header-link',
'contrast-more:[&>span]:!text-header-link',
'dark:bg-header-link/3',
'dark:ring-header-link/3',
'[&>span]:!text-header-link/7',
'dark:[&_svg]:text-header-link',
'dark:contrast-more:bg-transparent',
'dark:contrast-more:ring-header-link',
'dark:contrast-more:[&>span]:!text-header-link',
]
: null
}
>
<span className={tcls('flex-1')}>
{t(
getSpaceLanguage(customization),
customization.aiSearch.enabled ? 'search_or_ask' : 'search',
)}
</span>
</SearchButton>
</Suspense>
<div className="flex max-w-full shrink min-w-0 gap-2 lg:gap-4 justify-start items-center">
<HeaderMobileMenu
className={tcls(
'lg:hidden',
'-ml-2',
customization.header.preset ===
CustomizationHeaderPreset.Default
? ['text-dark', 'dark:text-light']
: 'text-header-link',
)}
/>
<HeaderLogo site={site} space={space} customization={customization} />
{!hasSiteSections && isMultiVariants ? (
<div className="z-20 shrink hidden sm:block">
<SpacesDropdown space={space} spaces={spaces} />
</div>
) : null}
</div>

{customization.header.links.length > 0 && (
<HeaderLinks>
{customization.header.links.map((link, index) => {
return (
<HeaderLink
key={index}
link={link}
context={context}
customization={customization}
/>
);
})}
<HeaderLinkMore
label={t(getSpaceLanguage(customization), 'more')}
links={customization.header.links}
context={context}
customization={customization}
/>
</HeaderLinks>
)}
<div
className={tcls(
'flex',
'md:w-56',
'grow-0',
'shrink-0',
'justify-self-end',
)}
>
<Suspense fallback={null}>
<SearchButton
style={
!isCustomizationDefault && withTopHeader
? [
'bg-header-link/2',
'dark:bg-header-link/2',
'hover:bg-header-link/3',
'dark:hover:bg-header-link/3',

'text-header-link/8',
'dark:text-header-link/8',
'hover:text-header-link',
'dark:hover:text-header-link',

'ring-header-link/4',
'dark:ring-header-link/4',
'hover:ring-header-link/5',
'dark:hover:ring-header-link/5',

'[&_svg]:text-header-link/10',
'dark:[&_svg]:text-header-link/10',
'[&_.shortcut]:text-header-link/8',
'dark:[&_.shortcut]:text-header-link/8',

'contrast-more:bg-header-background',
'contrast-more:text-header-link',
'contrast-more:ring-header-link',
'contrast-more:hover:bg-header-background',
'contrast-more:hover:ring-header-link',
'contrast-more:focus:text-header-link',
'contrast-more:focus:bg-header-background',
'contrast-more:focus:ring-header-link',
'dark:contrast-more:bg-header-background',
'dark:contrast-more:text-header-link',
'dark:contrast-more:ring-header-link',
'dark:contrast-more:hover:bg-header-background',
'dark:contrast-more:hover:ring-header-link',
'dark:contrast-more:focus:text-header-link',
'dark:contrast-more:focus:bg-header-background',
'dark:contrast-more:focus:ring-header-link',

'shadow-none',
]
: null
}
>
<span className={tcls('flex-1')}>
{t(
getSpaceLanguage(customization),
customization.aiSearch.enabled
? 'search_or_ask'
: 'search',
)}
...
</span>
</SearchButton>
</Suspense>
</div>
</div>
</div>
</div>
{sections ? (
<div
className={tcls(
'w-full shadow-thintop dark:shadow-light/1 bg-light dark:bg-dark mt-0.5',
'scroll-nojump',
'w-full',
// Handle long section tabs, particularly on smaller screens.
'overflow-x-auto hide-scroll',
)}
Expand Down
10 changes: 4 additions & 6 deletions packages/gitbook/src/components/Header/HeaderLink.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export async function HeaderLink(props: {
if (link.links && link.links.length > 0) {
return (
<Dropdown
className="shrink"
button={(buttonProps) => {
if (!target) {
return (
Expand Down Expand Up @@ -147,12 +148,9 @@ function HeaderItemButton(

function getHeaderLinkClassName(props: { headerPreset: CustomizationHeaderPreset }) {
return tcls(
'overflow-hidden',
'text-sm lg:text-base',
'flex flex-row items-center',
'whitespace-nowrap',
'flex items-center shrink',
'hover:text-header-link-400 dark:hover:text-light',
'truncate',
'min-w-0',

props.headerPreset === CustomizationHeaderPreset.Default
? ['text-dark/8', 'dark:text-light/8']
Expand All @@ -164,7 +162,7 @@ function HeaderItemLink(props: HeaderLinkNavItemProps) {
const { headerPreset, title, isDropdown, href, ...rest } = props;
return (
<Link href={href} className={getHeaderLinkClassName({ headerPreset })} {...rest}>
{title}
<span className="truncate min-w-0">{title}</span>
{isDropdown ? <DropdownChevron /> : null}
</Link>
);
Expand Down
21 changes: 14 additions & 7 deletions packages/gitbook/src/components/Header/HeaderLinkMore.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import React from 'react';
import { ContentRefContext, resolveContentRef } from '@/lib/references';
import { tcls } from '@/lib/tailwind';

import { Dropdown, DropdownMenu, DropdownMenuItem } from './Dropdown';
import { Dropdown, DropdownChevron, DropdownMenu, DropdownMenuItem } from './Dropdown';
import styles from './headerLinks.module.css';

/**
Expand All @@ -31,15 +31,22 @@ export function HeaderLinkMore(props: {
const renderButton = () => (
<button
className={tcls(
'px-1',
!isCustomizationDefault
? ['text-header-link-500']
: ['text-dark/8', 'dark:text-light/8', 'dark:hover:text-light'],
'hover:text-header-link-400',
isCustomizationDefault
? [
'text-dark/8',
'dark:text-light/8',
'hover:text-primary',
'dark:hover:text-primary',
]
: ['text-header-link', 'hover:text-header-link/8'],
'flex',
'gap-1',
'items-center',
)}
>
<span className="sr-only">{label}</span>
<Icon icon="ellipsis" className={tcls('opacity-6', 'size-3', 'ms-1')} />
<Icon icon="ellipsis" className={tcls('size-4')} />
<DropdownChevron />
</button>
);

Expand Down
Loading

0 comments on commit 23584c9

Please sign in to comment.