Skip to content

Commit 2cb27bd

Browse files
committed
Add a search page
1 parent 435a862 commit 2cb27bd

File tree

4 files changed

+148
-8
lines changed

4 files changed

+148
-8
lines changed

theme/gatsby-node.js

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,8 +148,17 @@ exports.createPages = async (
148148
component: path.resolve(`${__dirname}/src/layout/print.tsx`),
149149
context: {
150150
layout: 'print',
151-
data
152-
}
151+
data,
152+
},
153+
})
154+
155+
createPage({
156+
path: '/search',
157+
component: path.resolve(`${__dirname}/src/layout/search.tsx`),
158+
context: {
159+
layout: 'docs',
160+
data,
161+
},
153162
})
154163

155164
const fieldData = {

theme/src/components/Header.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1+
import { Box, Button, Flex, Heading, Icons, Logo } from '@committed/components'
2+
import { graphql, useStaticQuery } from 'gatsby'
13
import React from 'react'
2-
import { useStaticQuery, graphql, navigate } from 'gatsby'
34
import { ClearLink } from './Link'
4-
import { Box, Flex, Logo, Button, Heading, Icons } from '@committed/components'
55

66
export const Header = () => {
77
const {
88
site: {
99
siteMetadata: {
10-
header: { title, helpUrl, logo, links }
11-
}
12-
}
10+
header: { title, helpUrl, logo, links },
11+
},
12+
},
1313
} = useStaticQuery(
1414
graphql`
1515
query headerQuery {
@@ -50,14 +50,19 @@ export const Header = () => {
5050
</ClearLink>
5151
</Flex>
5252
{links
53-
.filter(link => link.link !== '' && link.text !== '')
53+
.filter((link) => link.link !== '' && link.text !== '')
5454
.map((link, key) => (
5555
<ClearLink key={key} href={link.link}>
5656
<Button color="inherit" variant="text">
5757
{link.text}
5858
</Button>
5959
</ClearLink>
6060
))}
61+
<ClearLink href="/search">
62+
<Button color="inherit" variant="text">
63+
<Icons.Search />
64+
</Button>
65+
</ClearLink>
6166
{helpUrl !== '' ? (
6267
<a href={helpUrl}>
6368
<Icons.Help />

theme/src/components/Search.tsx

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
import {
2+
Button,
3+
Card,
4+
CardContent,
5+
Form,
6+
List,
7+
ListItem,
8+
TextField,
9+
Typography,
10+
} from '@committed/components'
11+
import { Index } from 'elasticlunr'
12+
import React, {
13+
FC,
14+
useCallback,
15+
useContext,
16+
useEffect,
17+
useMemo,
18+
useState,
19+
} from 'react'
20+
import { DocsContext } from './Layout'
21+
22+
interface SearchProps {
23+
index: any
24+
}
25+
26+
// These are defined through gatsby-node.js in the elasticlunr config
27+
interface Result {
28+
id: string
29+
title: string
30+
description?: string
31+
body: string
32+
slug: string
33+
}
34+
35+
export const Search: FC<SearchProps> = (props: SearchProps) => {
36+
const { navigate } = useContext(DocsContext)
37+
38+
const [query, setQuery] = useState('')
39+
const [results, setResults] = useState<Result[]>([])
40+
41+
const index = useMemo(() => {
42+
return Index.load(props.index)
43+
}, props.index)
44+
45+
const search = useCallback(() => {
46+
// Consider: Should we stop if query.length < 3?
47+
48+
const r = index
49+
// Expand allows for partial matches (mer matches mermaid)
50+
.search(query, { expand: true })
51+
// Map over each ID and return the full document
52+
.map(({ ref }) => index.documentStore.getDoc(ref))
53+
54+
// Consider: Should be limit number of results?
55+
setResults(r)
56+
}, [index, query, setResults])
57+
58+
// Consider: Search as you type - possible not a good idea for larger sites?
59+
useEffect(() => search(), [query, search])
60+
61+
return (
62+
<>
63+
<Card>
64+
<CardContent>
65+
<Form display="flex" width={1} onSubmit={search}>
66+
<TextField
67+
flexGrow={1}
68+
id="query-input"
69+
label="Query"
70+
value={query}
71+
onChange={(e) => setQuery(e.target.value)}
72+
/>
73+
<Button color="primary">Search</Button>
74+
</Form>
75+
</CardContent>
76+
</Card>
77+
{results.length === 0 && query !== '' && (
78+
<Typography variant="body1" gutterBottom>
79+
Sorry, no results found for "<i>{query}</i>"
80+
</Typography>
81+
)}
82+
{results.length > 0 && (
83+
<Card>
84+
<CardContent>
85+
<Typography variant="body1" gutterBottom>
86+
Found {results.length} results for "<i>{query}</i>".
87+
</Typography>
88+
<List>
89+
{results.map((r) => (
90+
<ListItem
91+
key={r.id}
92+
button
93+
onClick={() => {
94+
navigate(r.slug)
95+
}}
96+
>
97+
{r.title}
98+
{r.description && <small>: {r.description}</small>}
99+
</ListItem>
100+
))}
101+
</List>
102+
</CardContent>
103+
</Card>
104+
)}
105+
</>
106+
)
107+
}

theme/src/layout/search.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { graphql } from 'gatsby'
2+
import React from 'react'
3+
import { Search } from '../components/Search'
4+
import '../style/mermaid.css'
5+
6+
export default ({ data }) => {
7+
const {
8+
siteSearchIndex: { index },
9+
} = data
10+
return <Search index={index} />
11+
}
12+
13+
export const pageQuery = graphql`
14+
query SearchIndexQuery {
15+
siteSearchIndex {
16+
index
17+
}
18+
}
19+
`

0 commit comments

Comments
 (0)