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
112 changes: 112 additions & 0 deletions src/theme/Navbar/Content/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import React, {type ReactNode} from 'react';
import clsx from 'clsx';
import {
useThemeConfig,
ErrorCauseBoundary,
ThemeClassNames,
} from '@docusaurus/theme-common';
import {
splitNavbarItems,
useNavbarMobileSidebar,
} from '@docusaurus/theme-common/internal';
import NavbarItem, {type Props as NavbarItemConfig} from '@theme/NavbarItem';
import NavbarColorModeToggle from '@theme/Navbar/ColorModeToggle';
import SearchBar from '@theme/SearchBar';
import NavbarMobileSidebarToggle from '@theme/Navbar/MobileSidebar/Toggle';
import NavbarLogo from '@theme/Navbar/Logo';
import NavbarSearch from '@theme/Navbar/Search';

import styles from './styles.module.css';


function useNavbarItems() {
// TODO temporary casting until ThemeConfig type is improved
return useThemeConfig().navbar.items as NavbarItemConfig[];
}

function NavbarItems({items}: {items: NavbarItemConfig[]}): ReactNode {
return (
<>
{items.map((item, i) => (
<ErrorCauseBoundary
key={i}
onError={(error) =>
new Error(
`A theme navbar item failed to render.
Please double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:
${JSON.stringify(item, null, 2)}`,
{cause: error},
)
}>
<NavbarItem {...item} />
</ErrorCauseBoundary>
))}
</>
);
}

function NavbarContentLayout({
left,
right,
}: {
left: ReactNode;
right: ReactNode;
}) {
return (
<div className="navbar__inner">
<div
className={clsx(
ThemeClassNames.layout.navbar.containerLeft,
'navbar__items',
)}>
{left}

</div>
<div
className={clsx(
ThemeClassNames.layout.navbar.containerRight,
'navbar__items navbar__items--right',
)}>
{right}
</div>
</div>
);
}

export default function NavbarContent(): ReactNode {
const mobileSidebar = useNavbarMobileSidebar();

const items = useNavbarItems();
const [leftItems, rightItems] = splitNavbarItems(items);

const searchBarItem = items.find((item) => item.type === 'search');

return (
<NavbarContentLayout
left={
// TODO stop hardcoding items?
<>
{!mobileSidebar.disabled && <NavbarMobileSidebarToggle />}
<div className={styles.navBarWrap}>
<NavbarLogo />
</div>

<NavbarItems items={leftItems} />
</>
}
right={
// TODO stop hardcoding items?
// Ask the user to add the respective navbar items => more flexible
<>
<NavbarItems items={rightItems} />
<NavbarColorModeToggle className={styles.colorModeToggle} />
{!searchBarItem && (
<NavbarSearch>
<SearchBar />
</NavbarSearch>
)}
</>
}
/>
);
}
32 changes: 32 additions & 0 deletions src/theme/Navbar/Content/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Hide color mode toggle in small viewports
*/
@media (max-width: 996px) {
.colorModeToggle {
display: none;
}
}

/*
Restore some Infima style that broke with CSS Cascade Layers
See https://github.com/facebook/docusaurus/pull/11142
*/
:global(.navbar__items--right) > :last-child {
padding-right: 0;
}


.navBarWrap {
display: inline-flex;
align-items: center;
border-radius: 8px;
/* background-color: white; */
/* border: 1px solid #ccc; */ /*<--uncommenting will give a border*/
transition: background-color 0.25s ease, box-shadow 0.25s ease;
}

.navBarWrap:hover {
background-color: rgba(0, 0, 0, 0.05);
border: 1px solid #ccc;
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15);
}