Skip to content

Commit

Permalink
Merge pull request #178 from Lehoczky/fix/172-only-use-function-optio…
Browse files Browse the repository at this point in the history
…ns-at-component-level

feat(docsearch): allow to set component props individually and inherit undefined ones from the config
  • Loading branch information
Baroshem authored Oct 23, 2023
2 parents eada41f + bb59a06 commit e5bd791
Show file tree
Hide file tree
Showing 11 changed files with 545 additions and 180 deletions.
10 changes: 9 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,13 @@
"@typescript-eslint/no-unused-vars": [
"off"
]
}
},
"overrides": [
{
"files": ["playground/pages/**"],
"rules": {
"vue/multi-word-component-names": "off"
}
}
]
}
252 changes: 241 additions & 11 deletions docs/content/2.advanced/3.docsearch.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ As DocSearch is an additional feature for @nuxt-modules/algolia, it needs two ad
npm install @docsearch/js @docsearch/css
```

```bash [PNPM]
pnpm add @docsearch/js @docsearch/css
```

::

## Configuration
Expand All @@ -31,11 +35,9 @@ You can easily configure DocSearch usage via the `docSearch` key in the module c

By default, it is set to `false`, which disables it and does not ship anything to your Nuxt app bundle.

This key is fully typed and links you to the [DocSearch API reference](https://docsearch.algolia.com/docs/api) for each key.

```javascript
```ts
// nuxt.config.ts
{
export default defineNuxtConfig({
algolia: {
apiKey: 'apiKey',
applicationId: 'applicationId',
Expand All @@ -44,26 +46,254 @@ This key is fully typed and links you to the [DocSearch API reference](https://d
indexName: 'indexName',
}
}
}
})
```

### Supported options

#### `indexName`

> `type: string` | **required**
Your Algolia index name.

#### `placeholder`

> `type: string` | `default: "Search docs" | **optional**
The placeholder of the input of the DocSearch pop-up modal.

#### `searchParameters`

> `type: SearchParameters` | **optional**
The [Algolia Search Parameters](https://www.algolia.com/doc/api-reference/search-api-parameters/).

#### `disableUserPersonalization`

> `type: boolean` | `default: false` | **optional**
Disable saving recent searches and favorites to the local storage.

#### `initialQuery`

> `type: string` | **optional**
The search input initial query.

#### `translations`

> `type: Partial<DocSearchTranslations>` | `default: docSearchTranslations` | **optional**
Allow translations of any raw text and aria-labels present in the DocSearch button or modal components.

<details><summary>docSearchTranslations</summary>
<div>

```ts
const translations: DocSearchTranslations = {
button: {
buttonText: 'Search',
buttonAriaLabel: 'Search',
},
modal: {
searchBox: {
resetButtonTitle: 'Clear the query',
resetButtonAriaLabel: 'Clear the query',
cancelButtonText: 'Cancel',
cancelButtonAriaLabel: 'Cancel',
},
startScreen: {
recentSearchesTitle: 'Recent',
noRecentSearchesText: 'No recent searches',
saveRecentSearchButtonTitle: 'Save this search',
removeRecentSearchButtonTitle: 'Remove this search from history',
favoriteSearchesTitle: 'Favorite',
removeFavoriteSearchButtonTitle: 'Remove this search from favorites',
},
errorScreen: {
titleText: 'Unable to fetch results',
helpText: 'You might want to check your network connection.',
},
footer: {
selectText: 'to select',
selectKeyAriaLabel: 'Enter key',
navigateText: 'to navigate',
navigateUpKeyAriaLabel: 'Arrow up',
navigateDownKeyAriaLabel: 'Arrow down',
closeText: 'to close',
closeKeyAriaLabel: 'Escape key',
searchByText: 'Search by',
},
noResultsScreen: {
noResultsText: 'No results for',
suggestedQueryText: 'Try searching for',
reportMissingResultsText: 'Believe this query should return results?',
reportMissingResultsLinkText: 'Let us know.',
},
},
};
```

You can find a list of every supported parameters by looking at the type definition ([DocSearchOptions](https://github.com/nuxt-modules/algolia/tree/main/src/types.ts)).
</div>
</details>

#### `facetFilters`

> `type: string` | **optional**
The facetFilters to use in your search parameters. This is local shorthand and provided by `@nuxtjs/algolia`.

This will be overwritten if you add `facetFilters` into your `searchOptions` object.

See [algolia facetFilters](https://www.algolia.com/doc/api-reference/api-parameters/facetFilters/)

#### `langAttribute`

> `type: string` | **optional**
## Usage
The language to prefix all your facetFilters with. This will be overwritten if you add `facetFilters` into your `searchOptions` object. This is local shorthand and provided by @nuxtjs/algolia.

#### `lang`

> `type: string` | `default: 'en'` | **optional**
Default language to be used on the Algolia DocSearch client.

## Component Usage

You can easily add the component anywhere in your app like this:

```vue
<template>
<AlgoliaDocSearch :options="options" />
<AlgoliaDocSearch />
</template>
```

The component will use the configuration values declared in `nuxt.config.ts`.

You can pass the configuration directly to the component as well if it's more convenient for you, like this:

```vue
<template>
<AlgoliaDocSearch
applicationId="appId"
apiKey="key"
indexName="indexName"
placeholder="Search"
:searchParameters="{}"
:disableUserPersonalization="false"
initialQuery=""
:translations="{}"
/>
</template>
```

`options` key is optional.
::alert{type="info"}

The component will try to resolve the configuration by itself via `useRuntimeConfig`.
If a specific option is set in both `nuxt.config.ts` and as a component prop, the latter takes precedence.

If you want to overwrite the config from your `nuxt.config`, you can pass the object via the prop.
::

### Additional Component Props

These options are only available as component props.

#### `transformItems`

> `type: function` | `default: items => items` | **optional**
Receives the items from the search response, and is called before displaying them. Should return a new array with the same shape as the original array. Useful for mapping over the items to transform, and remove or reorder them.

```vue
<template>
<AlgoliaDocSearch
:transform-items="(items) => {
return items.map((item) => ({
...item,
content: item.content.toUpperCase(),
}));
}"
/>
</template>
```

#### `hitComponent`

> `type: ({ hit, children }) => JSX.Element` | `default: Hit` | **optional**
The component to display each item.

See the [default implementation](https://github.com/algolia/docsearch/blob/main/packages/docsearch-react/src/Hit.tsx).

#### `transformSearchClient`

> `type: function` | `default: searchClient => searchClient` | **optional**
Useful for transforming the [Algolia Search Client](https://www.algolia.com/doc/api-client/getting-started/what-is-the-api-client/javascript/?client=javascript), for example to debounce search queries:

```vue
<template>
<AlgoliaDocSearch :transform-search-client="transformSearchClient" />
</template>
<script setup lang="ts">
import { SearchClient } from 'algoliasearch'
import { DocSearchProps } from 'docsearch'
const transformSearchClient: DocSearchProps['transformSearchClient'] = (searchClient) => {
return {
...searchClient,
search: debounce(searchClient.search, 5000)
} as SearchClient
}
function debounce (func: (...args: unknown[]) => unknown, wait = 100) {
let lastTimeout = null
return function (...args) {
const that = this
return new Promise((resolve, reject) => {
if (lastTimeout) {
clearTimeout(lastTimeout)
}
lastTimeout = setTimeout(() => {
lastTimeout = null
Promise.resolve(func.apply(that, args)).then(resolve).catch(reject)
}, wait)
})
}
}
</script>
```

#### `navigator`

> `type: Navigator` | **optional**
An implementation of [Algolia Autocomplete](https://www.algolia.com/doc/ui-libraries/autocomplete/introduction/what-is-autocomplete/)’s Navigator API to redirect the user when opening a link.

Learn more on the [Navigator API](https://www.algolia.com/doc/ui-libraries/autocomplete/core-concepts/keyboard-navigation/) documentation.

#### `getMissingResultsUrl`

> `type: ({ query: string }) => string` | **optional**
Function to return the URL of your documentation repository.

```vue
<template>
<AlgoliaDocSearch :get-missing-results-url="getMissingResultsUrl" />
</template>
<script setup lang="ts">
import { DocSearchProps } from 'docsearch'
const getMissingResultsUrl: DocSearchProps['getMissingResultsUrl'] = ({ query }) => {
return `https://github.com/algolia/docsearch/issues/new?title=${query}`;
}
</script>
```

## Theming

Expand Down
10 changes: 6 additions & 4 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@ export default defineNuxtConfig({
}
},
algolia: {
// apiKey: process.env.ALGOLIA_API_KEY,
// applicationId: process.env.ALGOLIA_APPLICATION_ID,
apiKey: process.env.ALGOLIA_API_KEY ?? '599cec31baffa4868cae4e79f180729b',
applicationId: process.env.ALGOLIA_APPLICATION_ID ?? 'R2IYF7ETH7',
lite: false, // by default set to 'true'
cache: true,
docSearch: {
indexName: process.env.ALGOLIA_DOCSEARCH_INDEX_NAME ?? 'indexName',
facetFilters: process.env.ALGOLIA_DOCSEARCH_FACET_FILTERS ?? ''
indexName: process.env.ALGOLIA_DOCSEARCH_INDEX_NAME ?? 'docsearch',
searchParameters: {
facetFilters: []
}
},
instantSearch: {
theme: 'algolia'
Expand Down
39 changes: 39 additions & 0 deletions playground/pages/docsearch.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<template>
<main>
<div v-if="isDocsearchEnabled">
<h1>DocSearch plugin</h1>

<div>
<NuxtLink to="/">
Home
</NuxtLink>
</div>
<div style="display: flex; gap: 0.5rem;margin-bottom: 3rem;">
<NuxtLink to="/docsearch">
Basic example
</NuxtLink>
<NuxtLink to="/docsearch/transform-items">
Transforming items
</NuxtLink>
<NuxtLink to="/docsearch/debounce-search">
Debouncing search
</NuxtLink>
</div>

<div>
<NuxtPage />
</div>
</div>

<div v-else>
DocSearch plugin is currently disabled.

See the <a href="https://algolia.nuxtjs.org/advanced/docsearch#configuration">configuration docs</a> on how to enable it.
</div>
</main>
</template>

<script setup lang="ts">
const { algolia: { docSearch } } = useRuntimeConfig().public
const isDocsearchEnabled = computed(() => Boolean(docSearch))
</script>
Loading

0 comments on commit e5bd791

Please sign in to comment.