summaryrefslogtreecommitdiff
path: root/docs/src/components/Header/Search.tsx
blob: 8f2cfe6497aebb67c705334e1e02e0de76e410b6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/* jsxImportSource: react */
import { useState, useCallback, useRef } from 'react';
import { createPortal } from 'react-dom';
import * as docsearch from '@docsearch/react';
import '@docsearch/css/dist/style.css';
import './Search.css';

const { DocSearchModal, useDocSearchKeyboardEvents } =
	(docsearch as unknown as { default: typeof docsearch }).default || docsearch;

export default function Search(props) {
	const [isOpen, setIsOpen] = useState(false);
	const searchButtonRef = useRef();
	const [initialQuery, setInitialQuery] = useState(null);
	const { lang = 'en' } = props;

	const onOpen = useCallback(() => {
		setIsOpen(true);
	}, [setIsOpen]);

	const onClose = useCallback(() => {
		setIsOpen(false);
	}, [setIsOpen]);

	const onInput = useCallback(
		(e) => {
			setIsOpen(true);
			setInitialQuery(e.key);
		},
		[setIsOpen, setInitialQuery]
	);

	useDocSearchKeyboardEvents({
		isOpen,
		onOpen,
		onClose,
		onInput,
		searchButtonRef,
	});

	return (
		<>
			<button
				type="button"
				ref={searchButtonRef}
				onClick={onOpen}
				className="search-input"
			>
				<svg width="24" height="24" fill="none">
					<path
						d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
						stroke="currentColor"
						strokeWidth="2"
						strokeLinecap="round"
						strokeLinejoin="round"
					/>
				</svg>
				<span className="search-placeholder">Search</span>
				<span className="search-hint">
					<span className="sr-only">Press </span>
					<kbd>/</kbd>
					<span className="sr-only"> to search</span>
				</span>
			</button>
			{isOpen &&
				createPortal(
					<DocSearchModal
						initialQuery={initialQuery}
						initialScrollY={window.scrollY}
						onClose={onClose}
						indexName="astro"
						apiKey="0f387260ad74f9cbf4353facd29c919c"
						// Set facetFilters once Astro docs have been indexed by language
						// searchParameters={{ facetFilters: [`lang:${lang}`] }}
						transformItems={(items) => {
							return items.map((item) => {
								// We transform the absolute URL into a relative URL to
								// work better on localhost, preview URLS.
								const a = document.createElement('a');
								a.href = item.url;
								const hash = a.hash === '#overview' ? '' : a.hash;
								return {
									...item,
									url: `${a.pathname}${hash}`,
								};
							});
						}}
					/>,
					document.body
				)}
		</>
	);
}