This is an automated email from the ASF dual-hosted git repository.
guoqi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
The following commit(s) were added to refs/heads/master by this push:
new 1c6b8aec976 fix: search bar, posts order, style (#1258)
1c6b8aec976 is described below
commit 1c6b8aec9769679613540219d7621b984cfbf494
Author: Young <[email protected]>
AuthorDate: Tue Aug 2 13:53:17 2022 +0800
fix: search bar, posts order, style (#1258)
---
blog/src/theme/BlogPosts/index.tsx | 19 ++-
blog/src/theme/BlogPosts/style.module.scss | 2 +-
blog/src/theme/SearchBar/index.js | 202 ++++++++++++++++++++++++++
blog/src/theme/SearchBar/styles.css | 22 +++
blog/src/theme/SearchBar/styles.module.css | 21 +++
doc/src/theme/SearchBar/index.js | 202 ++++++++++++++++++++++++++
doc/src/theme/SearchBar/styles.css | 22 +++
doc/src/theme/SearchBar/styles.module.css | 21 +++
website/src/theme/SearchBar/index.js | 202 ++++++++++++++++++++++++++
website/src/theme/SearchBar/styles.css | 22 +++
website/src/theme/SearchBar/styles.module.css | 21 +++
yarn.lock | 2 +-
12 files changed, 746 insertions(+), 12 deletions(-)
diff --git a/blog/src/theme/BlogPosts/index.tsx
b/blog/src/theme/BlogPosts/index.tsx
index 91bd6abcf87..5316246c0e8 100644
--- a/blog/src/theme/BlogPosts/index.tsx
+++ b/blog/src/theme/BlogPosts/index.tsx
@@ -70,7 +70,12 @@ const BlogPostItem: FC<BlogPostItemProps> = (props) => {
const image = assets?.image ?? frontMatter.image ?? defaultImg;
return (
- <article className={className} itemProp="blogPost" itemScope
itemType="http://schema.org/BlogPosting">
+ <article
+ className={className}
+ itemProp="blogPost"
+ itemScope
+ itemType="http://schema.org/BlogPosting"
+ >
<Link itemProp="url" to={permalink} aria-label={`Read more about
${title}`}>
<LazyLoadImage
height={232}
@@ -169,7 +174,7 @@ const BlogPosts: FC<BlogPostsProps> = ({
useIntersectionObserver,
...props
}) => {
- let posts = items.map(({ content: BlogPostContent }) => (
+ const posts = items.map(({ content: BlogPostContent }) => (
<BlogPostItem
key={BlogPostContent.metadata.permalink}
frontMatter={BlogPostContent.frontMatter}
@@ -182,10 +187,8 @@ const BlogPosts: FC<BlogPostsProps> = ({
</BlogPostItem>
));
- const max = (pickedPosts.length > 10 ? pickedPosts.length - 10 :
pickedPosts.length);
- const endIdx = isFirstPage
- ? 2 * Math.floor(max / 2)
- : 3 * Math.floor(max / 3);
+ const max = pickedPosts.length > 10 ? pickedPosts.length - 10 :
pickedPosts.length;
+ const endIdx = isFirstPage ? 2 * Math.floor(max / 2) : 3;
const { pathname } = useLocation();
if (!pathname.includes('/tags/')) {
@@ -212,10 +215,6 @@ const BlogPosts: FC<BlogPostsProps> = ({
</BlogPostItem>
)),
);
-
- if (!isFirstPage) {
- posts = shuffle(posts);
- }
}
return (
diff --git a/blog/src/theme/BlogPosts/style.module.scss
b/blog/src/theme/BlogPosts/style.module.scss
index bf6563e3e2b..f2f0cca0122 100644
--- a/blog/src/theme/BlogPosts/style.module.scss
+++ b/blog/src/theme/BlogPosts/style.module.scss
@@ -64,7 +64,7 @@
font-family: apple-system, system-ui, sans-serif;
article {
- margin: 0 1.25rem 2.5rem;
+ margin: 0 1.25rem 3rem;
border-radius: 1rem;
overflow: hidden;
border: 2px solid transparent;
diff --git a/blog/src/theme/SearchBar/index.js
b/blog/src/theme/SearchBar/index.js
new file mode 100644
index 00000000000..1c65093dee5
--- /dev/null
+++ b/blog/src/theme/SearchBar/index.js
@@ -0,0 +1,202 @@
+/* eslint-disable */
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, { useState, useRef, useCallback, useMemo } from 'react';
+import { createPortal } from 'react-dom';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import { useHistory } from '@docusaurus/router';
+import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
+import Head from '@docusaurus/Head';
+import useSearchQuery from '@theme/hooks/useSearchQuery';
+import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react';
+import useAlgoliaContextualFacetFilters from
'@theme/hooks/useAlgoliaContextualFacetFilters';
+import { translate } from '@docusaurus/Translate';
+import styles from './styles.module.css';
+
+let DocSearchModal = null;
+
+function Hit({ hit, children }) {
+ return <a href={hit.url}>{children}</a>;
+}
+
+function ResultsFooter({ state, onClose }) {
+ const { generateSearchPageLink } = useSearchQuery();
+
+ return (
+ <Link to={generateSearchPageLink(state.query)} onClick={onClose}
target="_blank">
+ See all {state.context.nbHits} results
+ </Link>
+ );
+}
+
+function DocSearch({ contextualSearch, ...props }) {
+ const { siteMetadata } = useDocusaurusContext();
+
+ const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
+
+ const configFacetFilters = props.searchParameters?.facetFilters ?? [];
+
+ const facetFilters = contextualSearch
+ ? // Merge contextual search filters with config filters
+ [...contextualSearchFacetFilters, ...configFacetFilters]
+ : // ... or use config facetFilters
+ configFacetFilters;
+
+ // we let user override default searchParameters if he wants to
+ const searchParameters = {
+ ...props.searchParameters,
+ facetFilters,
+ };
+
+ const { withBaseUrl } = useBaseUrlUtils();
+ const history = useHistory();
+ const searchContainer = useRef(null);
+ const searchButtonRef = useRef(null);
+ const [isOpen, setIsOpen] = useState(false);
+ const [initialQuery, setInitialQuery] = useState(null);
+
+ const importDocSearchModalIfNeeded = useCallback(() => {
+ if (DocSearchModal) {
+ return Promise.resolve();
+ }
+
+ return Promise.all([
+ import('@docsearch/react/modal'),
+ import('@docsearch/react/style'),
+ import('./styles.css'),
+ ]).then(([{ DocSearchModal: Modal }]) => {
+ DocSearchModal = Modal;
+ });
+ }, []);
+
+ const onOpen = useCallback(() => {
+ importDocSearchModalIfNeeded().then(() => {
+ searchContainer.current = document.createElement('div');
+ document.body.insertBefore(searchContainer.current,
document.body.firstChild);
+ setIsOpen(true);
+ });
+ }, [importDocSearchModalIfNeeded, setIsOpen]);
+
+ const onClose = useCallback(() => {
+ setIsOpen(false);
+ searchContainer.current.remove();
+ }, [setIsOpen]);
+
+ const onInput = useCallback(
+ (event) => {
+ importDocSearchModalIfNeeded().then(() => {
+ setIsOpen(true);
+ setInitialQuery(event.key);
+ });
+ },
+ [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery]
+ );
+
+ const navigator = useRef({
+ navigate({ itemUrl }) {
+ history.push(itemUrl);
+ },
+ }).current;
+
+ const transformItems = useRef((items) => {
+ return items.map((item) => {
+ // We transform the absolute URL into a relative URL.
+ // Alternatively, we can use `new URL(item.url)` but it's not
+ // supported in IE.
+ const a = document.createElement('a');
+ a.href = item.url;
+
+ return {
+ ...item,
+ url: withBaseUrl(`${a.pathname}${a.hash}`),
+ };
+ });
+ }).current;
+
+ const resultsFooterComponent = useMemo(
+ () => (footerProps) => <ResultsFooter {...footerProps} onClose={onClose}
/>,
+ [onClose]
+ );
+
+ const transformSearchClient = useCallback(
+ (searchClient) => {
+ searchClient.addAlgoliaAgent('docusaurus',
siteMetadata.docusaurusVersion);
+
+ return searchClient;
+ },
+ [siteMetadata.docusaurusVersion]
+ );
+
+ useDocSearchKeyboardEvents({
+ isOpen,
+ onOpen,
+ onClose,
+ onInput,
+ searchButtonRef,
+ });
+
+ const translatedSearchLabel = translate({
+ id: 'theme.SearchBar.label',
+ message: 'Search',
+ description: 'The ARIA label and placeholder for search button',
+ });
+
+ return (
+ <>
+ <Head>
+ {/* This hints the browser that the website will load data from
Algolia,
+ and allows it to preconnect to the DocSearch cluster. It makes the
first
+ query faster, especially on mobile. */}
+ <link
+ rel="preconnect"
+ href={`https://${props.appId}-dsn.algolia.net`}
+ crossOrigin="anonymous"
+ />
+ </Head>
+
+ <div className={styles.searchBox}>
+ <DocSearchButton
+ onTouchStart={importDocSearchModalIfNeeded}
+ onFocus={importDocSearchModalIfNeeded}
+ onMouseOver={importDocSearchModalIfNeeded}
+ onClick={onOpen}
+ ref={searchButtonRef}
+ translations={{
+ buttonText: translatedSearchLabel,
+ buttonAriaLabel: translatedSearchLabel,
+ }}
+ />
+ </div>
+
+ {isOpen &&
+ createPortal(
+ <DocSearchModal
+ onClose={onClose}
+ initialScrollY={window.scrollY}
+ initialQuery={initialQuery}
+ navigator={navigator}
+ transformItems={transformItems}
+ hitComponent={Hit}
+ resultsFooterComponent={resultsFooterComponent}
+ transformSearchClient={transformSearchClient}
+ {...props}
+ searchParameters={searchParameters}
+ />,
+ searchContainer.current
+ )}
+ </>
+ );
+}
+
+function SearchBar() {
+ const { siteConfig } = useDocusaurusContext();
+ return <DocSearch {...siteConfig.themeConfig.algolia} />;
+}
+
+export default SearchBar;
diff --git a/blog/src/theme/SearchBar/styles.css
b/blog/src/theme/SearchBar/styles.css
new file mode 100644
index 00000000000..d95b6d37a6c
--- /dev/null
+++ b/blog/src/theme/SearchBar/styles.css
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+:root {
+ --docsearch-primary-color: var(--ifm-color-primary);
+ --docsearch-text-color: var(--ifm-font-color-base);
+}
+
+.DocSearch-Button {
+ margin: 0;
+ transition:
+ all var(--ifm-transition-fast)
+ var(--ifm-transition-timing-default);
+}
+
+.DocSearch-Container {
+ z-index: calc(var(--ifm-z-index-fixed) + 1);
+}
diff --git a/blog/src/theme/SearchBar/styles.module.css
b/blog/src/theme/SearchBar/styles.module.css
new file mode 100644
index 00000000000..e0df0559d0e
--- /dev/null
+++ b/blog/src/theme/SearchBar/styles.module.css
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+@media (max-width: 996px) {
+ .searchBox {
+ position: absolute;
+ right: var(--ifm-navbar-padding-horizontal);
+ }
+}
+
+@media (min-width: 997px) {
+ .searchBox {
+ padding:
+ var(--ifm-navbar-item-padding-vertical)
+ var(--ifm-navbar-item-padding-horizontal);
+ }
+}
diff --git a/doc/src/theme/SearchBar/index.js b/doc/src/theme/SearchBar/index.js
new file mode 100644
index 00000000000..1c65093dee5
--- /dev/null
+++ b/doc/src/theme/SearchBar/index.js
@@ -0,0 +1,202 @@
+/* eslint-disable */
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, { useState, useRef, useCallback, useMemo } from 'react';
+import { createPortal } from 'react-dom';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import { useHistory } from '@docusaurus/router';
+import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
+import Head from '@docusaurus/Head';
+import useSearchQuery from '@theme/hooks/useSearchQuery';
+import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react';
+import useAlgoliaContextualFacetFilters from
'@theme/hooks/useAlgoliaContextualFacetFilters';
+import { translate } from '@docusaurus/Translate';
+import styles from './styles.module.css';
+
+let DocSearchModal = null;
+
+function Hit({ hit, children }) {
+ return <a href={hit.url}>{children}</a>;
+}
+
+function ResultsFooter({ state, onClose }) {
+ const { generateSearchPageLink } = useSearchQuery();
+
+ return (
+ <Link to={generateSearchPageLink(state.query)} onClick={onClose}
target="_blank">
+ See all {state.context.nbHits} results
+ </Link>
+ );
+}
+
+function DocSearch({ contextualSearch, ...props }) {
+ const { siteMetadata } = useDocusaurusContext();
+
+ const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
+
+ const configFacetFilters = props.searchParameters?.facetFilters ?? [];
+
+ const facetFilters = contextualSearch
+ ? // Merge contextual search filters with config filters
+ [...contextualSearchFacetFilters, ...configFacetFilters]
+ : // ... or use config facetFilters
+ configFacetFilters;
+
+ // we let user override default searchParameters if he wants to
+ const searchParameters = {
+ ...props.searchParameters,
+ facetFilters,
+ };
+
+ const { withBaseUrl } = useBaseUrlUtils();
+ const history = useHistory();
+ const searchContainer = useRef(null);
+ const searchButtonRef = useRef(null);
+ const [isOpen, setIsOpen] = useState(false);
+ const [initialQuery, setInitialQuery] = useState(null);
+
+ const importDocSearchModalIfNeeded = useCallback(() => {
+ if (DocSearchModal) {
+ return Promise.resolve();
+ }
+
+ return Promise.all([
+ import('@docsearch/react/modal'),
+ import('@docsearch/react/style'),
+ import('./styles.css'),
+ ]).then(([{ DocSearchModal: Modal }]) => {
+ DocSearchModal = Modal;
+ });
+ }, []);
+
+ const onOpen = useCallback(() => {
+ importDocSearchModalIfNeeded().then(() => {
+ searchContainer.current = document.createElement('div');
+ document.body.insertBefore(searchContainer.current,
document.body.firstChild);
+ setIsOpen(true);
+ });
+ }, [importDocSearchModalIfNeeded, setIsOpen]);
+
+ const onClose = useCallback(() => {
+ setIsOpen(false);
+ searchContainer.current.remove();
+ }, [setIsOpen]);
+
+ const onInput = useCallback(
+ (event) => {
+ importDocSearchModalIfNeeded().then(() => {
+ setIsOpen(true);
+ setInitialQuery(event.key);
+ });
+ },
+ [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery]
+ );
+
+ const navigator = useRef({
+ navigate({ itemUrl }) {
+ history.push(itemUrl);
+ },
+ }).current;
+
+ const transformItems = useRef((items) => {
+ return items.map((item) => {
+ // We transform the absolute URL into a relative URL.
+ // Alternatively, we can use `new URL(item.url)` but it's not
+ // supported in IE.
+ const a = document.createElement('a');
+ a.href = item.url;
+
+ return {
+ ...item,
+ url: withBaseUrl(`${a.pathname}${a.hash}`),
+ };
+ });
+ }).current;
+
+ const resultsFooterComponent = useMemo(
+ () => (footerProps) => <ResultsFooter {...footerProps} onClose={onClose}
/>,
+ [onClose]
+ );
+
+ const transformSearchClient = useCallback(
+ (searchClient) => {
+ searchClient.addAlgoliaAgent('docusaurus',
siteMetadata.docusaurusVersion);
+
+ return searchClient;
+ },
+ [siteMetadata.docusaurusVersion]
+ );
+
+ useDocSearchKeyboardEvents({
+ isOpen,
+ onOpen,
+ onClose,
+ onInput,
+ searchButtonRef,
+ });
+
+ const translatedSearchLabel = translate({
+ id: 'theme.SearchBar.label',
+ message: 'Search',
+ description: 'The ARIA label and placeholder for search button',
+ });
+
+ return (
+ <>
+ <Head>
+ {/* This hints the browser that the website will load data from
Algolia,
+ and allows it to preconnect to the DocSearch cluster. It makes the
first
+ query faster, especially on mobile. */}
+ <link
+ rel="preconnect"
+ href={`https://${props.appId}-dsn.algolia.net`}
+ crossOrigin="anonymous"
+ />
+ </Head>
+
+ <div className={styles.searchBox}>
+ <DocSearchButton
+ onTouchStart={importDocSearchModalIfNeeded}
+ onFocus={importDocSearchModalIfNeeded}
+ onMouseOver={importDocSearchModalIfNeeded}
+ onClick={onOpen}
+ ref={searchButtonRef}
+ translations={{
+ buttonText: translatedSearchLabel,
+ buttonAriaLabel: translatedSearchLabel,
+ }}
+ />
+ </div>
+
+ {isOpen &&
+ createPortal(
+ <DocSearchModal
+ onClose={onClose}
+ initialScrollY={window.scrollY}
+ initialQuery={initialQuery}
+ navigator={navigator}
+ transformItems={transformItems}
+ hitComponent={Hit}
+ resultsFooterComponent={resultsFooterComponent}
+ transformSearchClient={transformSearchClient}
+ {...props}
+ searchParameters={searchParameters}
+ />,
+ searchContainer.current
+ )}
+ </>
+ );
+}
+
+function SearchBar() {
+ const { siteConfig } = useDocusaurusContext();
+ return <DocSearch {...siteConfig.themeConfig.algolia} />;
+}
+
+export default SearchBar;
diff --git a/doc/src/theme/SearchBar/styles.css
b/doc/src/theme/SearchBar/styles.css
new file mode 100644
index 00000000000..d95b6d37a6c
--- /dev/null
+++ b/doc/src/theme/SearchBar/styles.css
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+:root {
+ --docsearch-primary-color: var(--ifm-color-primary);
+ --docsearch-text-color: var(--ifm-font-color-base);
+}
+
+.DocSearch-Button {
+ margin: 0;
+ transition:
+ all var(--ifm-transition-fast)
+ var(--ifm-transition-timing-default);
+}
+
+.DocSearch-Container {
+ z-index: calc(var(--ifm-z-index-fixed) + 1);
+}
diff --git a/doc/src/theme/SearchBar/styles.module.css
b/doc/src/theme/SearchBar/styles.module.css
new file mode 100644
index 00000000000..e0df0559d0e
--- /dev/null
+++ b/doc/src/theme/SearchBar/styles.module.css
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+@media (max-width: 996px) {
+ .searchBox {
+ position: absolute;
+ right: var(--ifm-navbar-padding-horizontal);
+ }
+}
+
+@media (min-width: 997px) {
+ .searchBox {
+ padding:
+ var(--ifm-navbar-item-padding-vertical)
+ var(--ifm-navbar-item-padding-horizontal);
+ }
+}
diff --git a/website/src/theme/SearchBar/index.js
b/website/src/theme/SearchBar/index.js
new file mode 100644
index 00000000000..1c65093dee5
--- /dev/null
+++ b/website/src/theme/SearchBar/index.js
@@ -0,0 +1,202 @@
+/* eslint-disable */
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import React, { useState, useRef, useCallback, useMemo } from 'react';
+import { createPortal } from 'react-dom';
+import useDocusaurusContext from '@docusaurus/useDocusaurusContext';
+import { useHistory } from '@docusaurus/router';
+import { useBaseUrlUtils } from '@docusaurus/useBaseUrl';
+import Link from '@docusaurus/Link';
+import Head from '@docusaurus/Head';
+import useSearchQuery from '@theme/hooks/useSearchQuery';
+import { DocSearchButton, useDocSearchKeyboardEvents } from '@docsearch/react';
+import useAlgoliaContextualFacetFilters from
'@theme/hooks/useAlgoliaContextualFacetFilters';
+import { translate } from '@docusaurus/Translate';
+import styles from './styles.module.css';
+
+let DocSearchModal = null;
+
+function Hit({ hit, children }) {
+ return <a href={hit.url}>{children}</a>;
+}
+
+function ResultsFooter({ state, onClose }) {
+ const { generateSearchPageLink } = useSearchQuery();
+
+ return (
+ <Link to={generateSearchPageLink(state.query)} onClick={onClose}
target="_blank">
+ See all {state.context.nbHits} results
+ </Link>
+ );
+}
+
+function DocSearch({ contextualSearch, ...props }) {
+ const { siteMetadata } = useDocusaurusContext();
+
+ const contextualSearchFacetFilters = useAlgoliaContextualFacetFilters();
+
+ const configFacetFilters = props.searchParameters?.facetFilters ?? [];
+
+ const facetFilters = contextualSearch
+ ? // Merge contextual search filters with config filters
+ [...contextualSearchFacetFilters, ...configFacetFilters]
+ : // ... or use config facetFilters
+ configFacetFilters;
+
+ // we let user override default searchParameters if he wants to
+ const searchParameters = {
+ ...props.searchParameters,
+ facetFilters,
+ };
+
+ const { withBaseUrl } = useBaseUrlUtils();
+ const history = useHistory();
+ const searchContainer = useRef(null);
+ const searchButtonRef = useRef(null);
+ const [isOpen, setIsOpen] = useState(false);
+ const [initialQuery, setInitialQuery] = useState(null);
+
+ const importDocSearchModalIfNeeded = useCallback(() => {
+ if (DocSearchModal) {
+ return Promise.resolve();
+ }
+
+ return Promise.all([
+ import('@docsearch/react/modal'),
+ import('@docsearch/react/style'),
+ import('./styles.css'),
+ ]).then(([{ DocSearchModal: Modal }]) => {
+ DocSearchModal = Modal;
+ });
+ }, []);
+
+ const onOpen = useCallback(() => {
+ importDocSearchModalIfNeeded().then(() => {
+ searchContainer.current = document.createElement('div');
+ document.body.insertBefore(searchContainer.current,
document.body.firstChild);
+ setIsOpen(true);
+ });
+ }, [importDocSearchModalIfNeeded, setIsOpen]);
+
+ const onClose = useCallback(() => {
+ setIsOpen(false);
+ searchContainer.current.remove();
+ }, [setIsOpen]);
+
+ const onInput = useCallback(
+ (event) => {
+ importDocSearchModalIfNeeded().then(() => {
+ setIsOpen(true);
+ setInitialQuery(event.key);
+ });
+ },
+ [importDocSearchModalIfNeeded, setIsOpen, setInitialQuery]
+ );
+
+ const navigator = useRef({
+ navigate({ itemUrl }) {
+ history.push(itemUrl);
+ },
+ }).current;
+
+ const transformItems = useRef((items) => {
+ return items.map((item) => {
+ // We transform the absolute URL into a relative URL.
+ // Alternatively, we can use `new URL(item.url)` but it's not
+ // supported in IE.
+ const a = document.createElement('a');
+ a.href = item.url;
+
+ return {
+ ...item,
+ url: withBaseUrl(`${a.pathname}${a.hash}`),
+ };
+ });
+ }).current;
+
+ const resultsFooterComponent = useMemo(
+ () => (footerProps) => <ResultsFooter {...footerProps} onClose={onClose}
/>,
+ [onClose]
+ );
+
+ const transformSearchClient = useCallback(
+ (searchClient) => {
+ searchClient.addAlgoliaAgent('docusaurus',
siteMetadata.docusaurusVersion);
+
+ return searchClient;
+ },
+ [siteMetadata.docusaurusVersion]
+ );
+
+ useDocSearchKeyboardEvents({
+ isOpen,
+ onOpen,
+ onClose,
+ onInput,
+ searchButtonRef,
+ });
+
+ const translatedSearchLabel = translate({
+ id: 'theme.SearchBar.label',
+ message: 'Search',
+ description: 'The ARIA label and placeholder for search button',
+ });
+
+ return (
+ <>
+ <Head>
+ {/* This hints the browser that the website will load data from
Algolia,
+ and allows it to preconnect to the DocSearch cluster. It makes the
first
+ query faster, especially on mobile. */}
+ <link
+ rel="preconnect"
+ href={`https://${props.appId}-dsn.algolia.net`}
+ crossOrigin="anonymous"
+ />
+ </Head>
+
+ <div className={styles.searchBox}>
+ <DocSearchButton
+ onTouchStart={importDocSearchModalIfNeeded}
+ onFocus={importDocSearchModalIfNeeded}
+ onMouseOver={importDocSearchModalIfNeeded}
+ onClick={onOpen}
+ ref={searchButtonRef}
+ translations={{
+ buttonText: translatedSearchLabel,
+ buttonAriaLabel: translatedSearchLabel,
+ }}
+ />
+ </div>
+
+ {isOpen &&
+ createPortal(
+ <DocSearchModal
+ onClose={onClose}
+ initialScrollY={window.scrollY}
+ initialQuery={initialQuery}
+ navigator={navigator}
+ transformItems={transformItems}
+ hitComponent={Hit}
+ resultsFooterComponent={resultsFooterComponent}
+ transformSearchClient={transformSearchClient}
+ {...props}
+ searchParameters={searchParameters}
+ />,
+ searchContainer.current
+ )}
+ </>
+ );
+}
+
+function SearchBar() {
+ const { siteConfig } = useDocusaurusContext();
+ return <DocSearch {...siteConfig.themeConfig.algolia} />;
+}
+
+export default SearchBar;
diff --git a/website/src/theme/SearchBar/styles.css
b/website/src/theme/SearchBar/styles.css
new file mode 100644
index 00000000000..d95b6d37a6c
--- /dev/null
+++ b/website/src/theme/SearchBar/styles.css
@@ -0,0 +1,22 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+:root {
+ --docsearch-primary-color: var(--ifm-color-primary);
+ --docsearch-text-color: var(--ifm-font-color-base);
+}
+
+.DocSearch-Button {
+ margin: 0;
+ transition:
+ all var(--ifm-transition-fast)
+ var(--ifm-transition-timing-default);
+}
+
+.DocSearch-Container {
+ z-index: calc(var(--ifm-z-index-fixed) + 1);
+}
diff --git a/website/src/theme/SearchBar/styles.module.css
b/website/src/theme/SearchBar/styles.module.css
new file mode 100644
index 00000000000..e0df0559d0e
--- /dev/null
+++ b/website/src/theme/SearchBar/styles.module.css
@@ -0,0 +1,21 @@
+/**
+ * Copyright (c) Facebook, Inc. and its affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+@media (max-width: 996px) {
+ .searchBox {
+ position: absolute;
+ right: var(--ifm-navbar-padding-horizontal);
+ }
+}
+
+@media (min-width: 997px) {
+ .searchBox {
+ padding:
+ var(--ifm-navbar-item-padding-vertical)
+ var(--ifm-navbar-item-padding-horizontal);
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 488a75f9f69..3a5ce5b42b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11500,7 +11500,7 @@ [email protected], style-to-object@^0.3.0:
dependencies:
inline-style-parser "0.1.1"
-styled-components@^5, styled-components@^5.3.3:
+styled-components@^5.3.3:
version "5.3.5"
resolved
"https://registry.yarnpkg.com/styled-components/-/styled-components-5.3.5.tgz#a750a398d01f1ca73af16a241dec3da6deae5ec4"
integrity
sha512-ndETJ9RKaaL6q41B69WudeqLzOpY1A/ET/glXkNZ2T7dPjPqpPCXXQjDFYZWwNnE5co0wX+gTCqx9mfxTmSIPg==