Skip to content

Commit b3b658f

Browse files
lex111slorber
andauthored
feat(v2): allow to change location of search bar (#4199)
* feat(v2): allow to change location of search bar * add SearchBar swizzle comment * quickfix for NavbarItem theme config * typing quickfix * doc typo Co-authored-by: slorber <[email protected]>
1 parent 2a12869 commit b3b658f

File tree

10 files changed

+91
-24
lines changed

10 files changed

+91
-24
lines changed

packages/docusaurus-theme-classic/src/theme/Navbar/index.tsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ function Navbar(): JSX.Element {
4444
navbar: {items, hideOnScroll, style},
4545
colorMode: {disableSwitch: disableColorModeSwitch},
4646
} = useThemeConfig();
47-
4847
const [sidebarShown, setSidebarShown] = useState(false);
49-
const [isSearchBarExpanded, setIsSearchBarExpanded] = useState(false);
50-
5148
const {isDarkTheme, setLightTheme, setDarkTheme} = useThemeContext();
5249
const {navbarRef, isNavbarVisible} = useHideableNavbar(hideOnScroll);
5350

@@ -73,6 +70,7 @@ function Navbar(): JSX.Element {
7370
}
7471
}, [windowSize]);
7572

73+
const hasSearchNavbarItem = items.some((item) => item.type === 'search');
7674
const {leftItems, rightItems} = splitNavItemsByPosition(items);
7775

7876
return (
@@ -101,9 +99,7 @@ function Navbar(): JSX.Element {
10199
<Logo
102100
className="navbar__brand"
103101
imageClassName="navbar__logo"
104-
titleClassName={clsx('navbar__title', {
105-
[styles.hideLogoText]: isSearchBarExpanded,
106-
})}
102+
titleClassName={clsx('navbar__title')}
107103
/>
108104
{leftItems.map((item, i) => (
109105
<NavbarItem {...item} key={i} />
@@ -121,10 +117,7 @@ function Navbar(): JSX.Element {
121117
onChange={onToggleChange}
122118
/>
123119
)}
124-
<SearchBar
125-
handleSearchBarToggle={setIsSearchBarExpanded}
126-
isSearchBarExpanded={isSearchBarExpanded}
127-
/>
120+
{!hasSearchNavbarItem && <SearchBar />}
128121
</div>
129122
</div>
130123
<div
@@ -152,7 +145,12 @@ function Navbar(): JSX.Element {
152145
<div className="menu">
153146
<ul className="menu__list">
154147
{items.map((item, i) => (
155-
<NavbarItem mobile {...item} onClick={hideSidebar} key={i} />
148+
<NavbarItem
149+
mobile
150+
{...(item as any)} // TODO fix typing
151+
onClick={hideSidebar}
152+
key={i}
153+
/>
156154
))}
157155
</ul>
158156
</div>

packages/docusaurus-theme-classic/src/theme/Navbar/styles.module.css

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,6 @@
1111
}
1212
}
1313

14-
@media (max-width: 768px) {
15-
.hideLogoText {
16-
display: none;
17-
}
18-
}
19-
2014
.navbarHideable {
2115
transition: transform var(--ifm-transition-fast) ease;
2216
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
import React from 'react';
9+
import type {Props} from '@theme/NavbarItem/SearchNavbarItem';
10+
import SearchBar from '@theme/SearchBar';
11+
import styles from './styles.module.css';
12+
13+
export default function SearchNavbarItem({mobile}: Props): JSX.Element | null {
14+
if (mobile) {
15+
return null;
16+
}
17+
18+
return (
19+
<div className={styles.searchWrapper}>
20+
<SearchBar />
21+
</div>
22+
);
23+
}

packages/docusaurus-theme-classic/src/theme/NavbarItem/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
import React from 'react';
99
import DefaultNavbarItem from '@theme/NavbarItem/DefaultNavbarItem';
1010
import LocaleDropdownNavbarItem from '@theme/NavbarItem/LocaleDropdownNavbarItem';
11+
import SearchNavbarItem from '@theme/NavbarItem/SearchNavbarItem';
1112
import type {Props} from '@theme/NavbarItem';
1213

1314
const NavbarItemComponents = {
1415
default: () => DefaultNavbarItem,
1516
localeDropdown: () => LocaleDropdownNavbarItem,
17+
search: () => SearchNavbarItem,
1618

1719
// Need to lazy load these items as we don't know for sure the docs plugin is loaded
1820
// See https://github.com/facebook/docusaurus/issues/3360
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
@media (max-width: 996px) {
9+
.searchWrapper {
10+
position: absolute;
11+
right: var(--ifm-navbar-padding-horizontal);
12+
}
13+
}

packages/docusaurus-theme-classic/src/theme/SearchBar.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,8 @@
55
* LICENSE file in the root directory of this source tree.
66
*/
77

8+
// By default, the classic theme does not provide any SearchBar implementation
9+
// If you swizzled this file, it is your responsibility to provide an implementation
10+
// Tip: swizzle the SearchBar from the Algolia theme for inspiration:
11+
// npm run swizzle @docusaurus/theme-search-algolia SearchBar
812
export {default} from '@docusaurus/Noop';

packages/docusaurus-theme-classic/src/types.d.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,13 @@ declare module '@theme/NavbarItem/DefaultNavbarItem' {
312312
export default DefaultNavbarItem;
313313
}
314314

315+
declare module '@theme/NavbarItem/SearchNavbarItem' {
316+
export type Props = {readonly mobile?: boolean};
317+
318+
const SearchNavbarItem: (props: Props) => JSX.Element;
319+
export default SearchNavbarItem;
320+
}
321+
315322
declare module '@theme/NavbarItem/LocaleDropdownNavbarItem' {
316323
import type {Props as DefaultNavbarItemProps} from '@theme/NavbarItem/DefaultNavbarItem';
317324
import type {NavLinkProps} from '@theme/NavbarItem/DefaultNavbarItem';
@@ -366,13 +373,15 @@ declare module '@theme/NavbarItem' {
366373
import type {Props as DefaultNavbarItemProps} from '@theme/NavbarItem/DefaultNavbarItem';
367374
import type {Props as DocsVersionDropdownNavbarItemProps} from '@theme/NavbarItem/DocsVersionDropdownNavbarItem';
368375
import type {Props as DocsVersionNavbarItemProps} from '@theme/NavbarItem/DocsVersionNavbarItem';
376+
import type {Props as SearchNavbarItemProps} from '@theme/NavbarItem/SearchNavbarItem';
369377

370378
export type Props =
371379
| ({readonly type?: 'default' | undefined} & DefaultNavbarItemProps)
372380
| ({
373381
readonly type: 'docsVersionDropdown';
374382
} & DocsVersionDropdownNavbarItemProps)
375-
| ({readonly type: 'docsVersion'} & DocsVersionNavbarItemProps);
383+
| ({readonly type: 'docsVersion'} & DocsVersionNavbarItemProps)
384+
| ({readonly type: 'search'} & SearchNavbarItemProps);
376385

377386
const NavbarItem: (props: Props) => JSX.Element;
378387
export default NavbarItem;

packages/docusaurus-theme-classic/src/validateThemeConfig.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,11 @@ const LocaleDropdownNavbarItemSchema = Joi.object({
107107
className: Joi.string(),
108108
});
109109

110+
const SearchItemSchema = Joi.object({
111+
type: Joi.string().equal('search').required(),
112+
position: NavbarItemPosition,
113+
});
114+
110115
// Can this be made easier? :/
111116
const isOfType = (type) => {
112117
let typeSchema = Joi.string().required();
@@ -139,6 +144,10 @@ const NavbarItemSchema = Joi.object().when({
139144
is: isOfType('localeDropdown'),
140145
then: LocaleDropdownNavbarItemSchema,
141146
},
147+
{
148+
is: isOfType('search'),
149+
then: SearchItemSchema,
150+
},
142151
{
143152
is: isOfType(undefined),
144153
then: Joi.forbidden().messages({

packages/docusaurus-theme-common/src/utils/useThemeConfig.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
88

99
export type DocsVersionPersistence = 'localStorage' | 'none';
1010

11-
// TODO improve
11+
// TODO improve types, use unions
1212
export type NavbarItem = {
13+
type?: string | undefined;
1314
items?: NavbarItem[];
1415
label?: string;
1516
};

website/docs/api/themes/theme-configuration.md

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -395,12 +395,26 @@ module.exports = {
395395
};
396396
```
397397

398-
````
398+
### Navbar search
399+
400+
If you use the [search](../../search.md), the search bar will be the rightmost element in the navbar.
401+
402+
However, with this special navbar item type, you can change the default location.
403+
404+
```js {5-8} title="docusaurus.config.js"
405+
module.exports = {
406+
themeConfig: {
407+
navbar: {
408+
items: [
399409
{
400-
type: 'localeDropdown',
401-
position: 'left',
410+
type: 'search',
411+
position: 'right',
402412
},
403-
```
413+
],
414+
},
415+
},
416+
};
417+
```
404418

405419
### Auto-hide sticky navbar
406420

@@ -416,7 +430,7 @@ module.exports = {
416430
// ...
417431
},
418432
};
419-
````
433+
```
420434

421435
### Navbar style
422436

0 commit comments

Comments
 (0)