React

How to use elasticlunr plugin with MDX

Creating a Search Bar component with Elasticlurn and MDX

Table of Contents
  1. Installing and Configuration
  2. Search Bar Component
  3. Importing and Using the Search Bar

Since I've recently moved from using markdownRemark to MDX on all my Gatsby Sites, the instructions to some plugins might not be that straightforward to follow. Recently, I've created a Digital Garden and wanted to add a search bar to it.

On one of my first Gatsby projects, I had used the Elasticlurn Plugin for Gatsby to add a search bar to a website. I decided to try and use this plugin since I don't have to use an external service like Algolia.

Installing and Configuration

Installing the plugin is pretty straightforward. You need to run the command:

shell
1npm install @gatsby-contrib/gatsby-plugin-elasticlunr-search

Then on your gatsby-config.js file, you can add the configuration for the plugin. If you read the README.md, you can see that one of the configuration options is the resolvers, here you need to replace MarkdownRemark for Mdx.

javascript
1{
2 resolve: `@gatsby-contrib/gatsby-plugin-elasticlunr-search`,
3 options: {
4 fields: [`title`, `category`, `tags`, `excerpt` ],
5 resolvers: {
6 Mdx: {
7 title: node => node.frontmatter.title,
8 category: node => node.frontmatter.category,
9 tags: node => node.frontmatter.tags,
10 excerpt: node => node.frontmatter.excerpt,
11 slug: node => node.fields.slug
12 }
13 },
14 filter: (node, getNode) => node.frontmatter.category
15 }
16 }

My frontmatter contains all those fields (but the slug). These are the fields that I want users to be able to search. You can choose as many or as little as you want.

Search Bar Component

With the plugin installed and configured, we have to create the search bar component. I re-used the component that I had created on the other project.

Note: This component needs refactoring. Most of this code was taken from the plugin instructions.

javascript
1import React, { Component } from "react"
2import { Index } from "elasticlunr"
3import { Link } from "gatsby"
4
5export default class Search extends Component {
6 constructor(props) {
7 super(props)
8 this.state = {
9 query: ``,
10 results: []
11 }
12 }
13
14 render() {
15 return (
16 <div className="my-5 relative">
17 <div className="flex justify-center items-center">
18 <i className="gg-search mr-2" />
19 <input type="text" value={this.state.query} onChange={this.search} placeholder="Search..." />
20 </div>
21 {this.state.results.length !== 0 ?
22 <div className="mt-2 flex flex-col absolute z-10 search-results">
23 {this.state.results.map(page => (
24 <Link className="link m-1" to={`${page.slug}`} key={page.title}>
25 <span className="underline">{page.title}</span> : <span className="green">{page.tags.join(', ')}</span>
26 </Link>
27
28 ))}
29 </div>
30 : ''}
31 </div>
32 )
33 }
34
35 getOrCreateIndex = () =>
36 this.index ? this.index : Index.load(this.props.searchIndex)
37
38 search = evt => {
39 const query = evt.target.value
40 this.index = this.getOrCreateIndex()
41 this.setState({
42 query,
43 results: this.index
44 .search(query, { expand: true})
45 .map(({ ref }) => this.index.documentStore.getDoc(ref))
46 })
47 }
48}

I want users to get partial matches straight away. So when you type something, you will get all matches first. Then the query will return fewer results. If you don't want this to happen and return the search results instead, you can remove the { expand: true } parameter from the search method.

You can probably see that on this site I am using TailwindCss. The only bit of CSS that I added outside Tailwind was the search-results which adds some styling(colour, spacing) to that div. The reason why I decided to use an absolute position, is because I want the search results to drop down and stay above the content.

Now that the search bar component is completed, you can use it anywhere on your site by importing it. But you also need to provide a searchIndex to the component. Luckily, the plugin adds a query for you to use.

graphql
1query {
2 siteSearchIndex {
3 index
4 }
5}

Then you can import the search bar component and use it like this:

javascript
1<SearchBar searchIndex={props.data.siteSearchIndex.index} />

That's all there is to add a search bar with elasticlunr plugin and MDX. If you have any issues feel free to reach me on Twitter @FabioRosado, I will be happy to give you a hand!


References:

Webmentions

0 Like 0 Comment

You might also like these

How to create a function to filter articles by tag. On this post I am using the javascript filter method to filter all articles.

Read More
React

How to filter all MDX articles by tags

How to filter all MDX articles by tags

How to add syntax highlighting to gatsby MDX with prism.

Read More
React

Add code highlighting to MDX

Add code highlighting to MDX

How to set up an UI element persistent in Gatsby to allow users from Landing in Tech to listen to the latest episode, when navigating the site.

Read More
React

How to make a UI element persistent in Gatsby

How to make a UI element persistent in Gatsby

Exploration on how to run Pyscript in a React (NextJS) app, this article explores issues and solutions to run PyScript in a React app.

Read More
PyScript

How to run PyScript in React

How to run PyScript in React