@hashicorp/react-search
v6.6.0
Published
Algolia-powered search component
Downloads
2,137
Maintainers
Keywords
Readme
@hashicorp/react-search
Props
renderHitContent
function
|({ hit: object, Highlight: React.Node }) => React.Component
| Required
A render function whose result is used to display each query "hit"
Params
| Property | Type | Description |
| --------- | ------------ | ----------------------------------------------------------------------------------- |
| hit | object
| https://www.algolia.com/doc/api-reference/widgets/highlight/react/#widget-param-hit |
| Highlight | React.Node
| https://www.algolia.com/doc/api-reference/widgets/highlight/react/ |
resolveHitLink
function
| |( hit: object ) => NextLinkProps
| Optional | Default: (hit) => ({ href:/${hit.objectID}
})
A function whose return value is spread as props to next/link
.
For more information about the available props, reference the next/link documentation: https://nextjs.org/docs/api-reference/next/link
Params
| Property | Type | Description |
| -------- | -------- | ----------------------------------------------------------------------------------- |
| hit | object
| https://www.algolia.com/doc/api-reference/widgets/highlight/react/#widget-param-hit |
placeholder
string
| Optional | Default:Search
Usage
import Search from '@hashicorp/react-search'
function SearchBar() {
return (
<Search
renderHitContent={({ hit, Highlight }) => <div>...</div>}
resolveHitLink={(hit) => ({ href: { pathname: `/${hit.objectID}`, query: { id: hit.__queryID} } })}
placeholder="Search documentation"
/>
}
Environment Variables
This component relies on the presence of the following environment variables to be available client side:
NEXT_PUBLIC_ALGOLIA_APP_ID
NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_API_KEY
NEXT_PUBLIC_ALGOLIA_INDEX
React
To use the primary <Search />
component, ensure it exists as a child of the <SearchProvider />
component. For example:
App.jsx
import Search, { SearchProvider } from '@hashicorp/react-search'
function App() {
return (
<>
<SearchProvider>
<Search
renderHitContent={({hit, Highlight}) => (
<span className="name">
<Highlight attribute="name" hit={hit} tagName="span" />
</span>
)}
resolveHitLink={(hit) => ({ href: `/${hit.objectID}` })}
/>
<ComponentA>
<ComponentB>
</SearchProvider>
<ComponentC__WithoutSearchContext>
</>
)
}
Any child component of <SearchProvider />
can utilize the provided useSearch()
hook and access search-specific information. For example:
import { useSearch } from '@hashicorp/react-search'
function ComponentA() {
const { query } = useSearch()
return <code>Search query: {query}</code>
}
useSearch()
useSearch()
exposes the following values:
client
(object
) - Initialized Algolia clientindexName
(string
) - The name of the Algolia index that search is performed uponinitAlgoliaInsights
(function
) - Required to initialize AlgoliaisCancelled
(boolean
) - Indicates if search is currently cancelled or notlogClick
(function
) - Fires an analytics event via thesearch-insights
packagequery
(string
) - Current search querysetIsCancelled
(function
) - Setter function that updates the search cancel statesetQuery
(function
) - Setter function that updates the search query
Tools
This package includes a tools.js
file that includes Algolia-related Node.js scripts
Usage
const {
indexDocsContent,
indexContent,
} = require('@hashicorp/react-search/tools')
/* It's worth noting that you'd only want to use *one* of the two exported functions */
indexDocsContent
function
|(config: object)
This specific helper function is designed specifically for perfoming search indexing on our various product sites' documentation pages.
config.algoliaConfig: { appId: string, apiKey: string, index: string }
Algolia-related configuration
Default:
{
apiKey: process.env.ALGOLIA_API_KEY,
appId: process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
index: process.env.NEXT_PUBLIC_ALGOLIA_INDEX,
}
config.contentDir: string
Path to directory that contains the content to be indexed by Algolia
Default: path.join(__dirname, 'pages')
config.filesPattern: string
minimatch-style string to be performed within config.contentDir
. The results of this pattern match will determine which files to index.
Default: '**/*.mdx'
config.globOptions: { [k:string]: any }
Additional options to include to the glob match. Available options here
Default: { ignore: path.join(config.contentDir, 'partials/**/*') }
config.frontmatterKeys: string[]
Assuming your search-indexed content includes frontmatter, the keys included in this array
will be included as search criteria.
Default: ['page_title', 'description']
indexContent
function
|(config: object)
This generic helper function allows for custom Algolia indexing
config.algoliaConfig: { appId: string, apiKey: string, index: string }
Algolia-related configuration
Default:
{
apiKey: process.env.ALGOLIA_API_KEY,
appId: process.env.NEXT_PUBLIC_ALGOLIA_APP_ID,
index: process.env.NEXT_PUBLIC_ALGOLIA_INDEX,
}
config.getSearchObjects: () => any
This function should return an array of objects that will get passed to Algolias partialUpdateObjects
function
Setting Up Algolia
In order for this component to work at all, you will need to configure an algolia index. Steps to manage this are below:
Log in to algolia.com using HashiCorp SSO. If you do not have access to algolia, reach out to IT and request access.
Within algolia, select "incices", then "create new index". See existing indices for naming patterns when choosing your index name. For docs sites, it is usually
product_NAME
.In your local
.env
file, use the index name as yourNEXT_PUBLIC_ALGOLIA_INDEX
valueMake sure that you have created a file in your project that runs the
indexDocsContent
script out of `tools. The file should be quite simple, and look like this:const { indexDocsContent } = require('@hashicorp/react-search/tools') indexDocsContent()
Typically we run this script via circleci. Head over to your project's circle configuration and add a block along these lines to jobs:
jobs: algolia-index: docker: - image: docker.mirror.hashicorp.services/node:12 steps: - checkout - run: name: Push content to Algolia Index command: | cd website/ npm install node scripts/index_search_content.js
Then make sure to run the job in the workflows section as well, only when the website is deployed. For docs sites this is on merge to the
stable-website
branch. For most other HashiCorp websites, this is on merge tomain
ormaster
.workflows: - algolia-index: filters: branches: only: - stable-website
Next, you'll want to setup two API keys for (1) searching and (2) indexing. Our Algolia keys are currently managed via a Terraform configuration. The ACL for the keys should be configured as follows:
| Index | ACL | Example Descrption | |-----------|--------------------------------------------------------------------------------------------|-------------------------------------| | search |
search
,browse
,listIndexes
|{product/project name}: search UI
| | index |addObject
,deleteObject
,search
,browse
,listIndexes
,settings
,editSettings
|{product/project name}: write key
|Open a PR to update the Terraform Configuration with the new pair of keys.
Grab the
index
API key, which is sensitive and should not be public, and add it to the environment variables in circleci asALGOLIA_API_KEY
.Grab the
search
API key, which is public, and add it to the.env
file in the project:NEXT_PUBLIC_ALGOLIA_SEARCH_ONLY_API_KEY=xxxx
.With this in place, you should be all set! Run the index script once locally, manually setting the algolia API key (like
ALGOLIA_API_KEY=xxxx node scripts/index_search_content.js
) to seed the index and make sure that the component is fully functional locally, then everything should be set!