Skip to content

Commit

Permalink
Use Algolia UI widgets for docs search (#847)
Browse files Browse the repository at this point in the history
  • Loading branch information
petyosi authored Feb 10, 2025
1 parent da4bb38 commit 8bd85d4
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 129 deletions.
22 changes: 22 additions & 0 deletions docs/extra/tweaks.css
Original file line number Diff line number Diff line change
Expand Up @@ -79,3 +79,25 @@ li.md-nav__item>a[href^="#logfire.configure("] {
.md-search__output em {
color: var(--md-primary-fg-color);
}

.md-search__input::-webkit-search-decoration,
.md-search__input::-webkit-search-cancel-button,
.md-search__input::-webkit-search-results-button,
.md-search__input::-webkit-search-results-decoration {
-webkit-appearance:none;
}

.md-search-result__article {
padding-bottom: .55em;
}

.ais-SearchBox-form {
display: flex;
flex-direction: row;
gap: 10px;
}

.md-search-result mark.ais-Highlight-highlighted,
.md-search-result mark.ais-Snippet-highlighted {
color: var(--md-primary-fg-color);
}
107 changes: 107 additions & 0 deletions docs/javascripts/algolia-search.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
const ALGOLIA_APP_ID = 'KPPUDTIAVX';
const ALGOLIA_API_KEY = '1fc841595212a2c3afe8c24dd4cb8790';
const ALGOLIA_INDEX_NAME = 'alt-logfire-docs';

const { liteClient: algoliasearch } = window['algoliasearch/lite'];
const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_API_KEY);

const search = instantsearch({
indexName: ALGOLIA_INDEX_NAME,
searchClient,
searchFunction(helper) {
const query = helper.state.query

if (query && query.length > 1) {
document.querySelector('#hits').hidden = false
document.querySelector('#type-to-start-searching').hidden = true
helper.search();
} else {
document.querySelector('#hits').hidden = true
document.querySelector('#type-to-start-searching').hidden = false
}
},
});

// create custom widget, to integrate with MkDocs built-in markup
const customSearchBox = instantsearch.connectors.connectSearchBox((renderOptions, isFirstRender) => {
const { query, refine, clear } = renderOptions;

if (isFirstRender) {
document.querySelector('#searchbox').addEventListener('input', event => {
refine(event.target.value);
});

document.querySelector('#searchbox').addEventListener('focus', () => {
document.querySelector('#__search').checked = true;
});

document.querySelector('#searchbox-clear').addEventListener('click', () => {
clear();
});

document.querySelector('#searchbox').addEventListener('keydown', (event) => {
// on down arrow, find the first search result and focus it
if (event.key === 'ArrowDown') {
document.querySelector('.md-search-result__link').focus();
event.preventDefault();
}
});

// for Hits, add keyboard navigation
document.querySelector('#hits').addEventListener('keydown', (event) => {
if (event.key === 'ArrowDown') {
const next = event.target.parentElement.nextElementSibling;
if (next) {
next.querySelector('.md-search-result__link').focus();
event.preventDefault();
}
} else if (event.key === 'ArrowUp') {
const prev = event.target.parentElement.previousElementSibling;
if (prev) {
prev.querySelector('.md-search-result__link').focus();
} else {
document.querySelector('#searchbox').focus();
}
event.preventDefault();
}
})

document.addEventListener('keydown', (event) => {
// if forward slash is pressed, focus the search box
if (event.key === '/' && event.target.tagName !== 'INPUT') {
document.querySelector('#searchbox').focus();
event.preventDefault();
}
})
}


document.querySelector('#type-to-start-searching').hidden = query.length > 1;
document.querySelector('#searchbox').value = query;
});

search.addWidgets([
customSearchBox({}),

instantsearch.widgets.hits({
container: '#hits',
cssClasses: {
'list': 'md-search-result__list',
'item': 'md-search-result__item'
},
templates: {
item: (hit, { html, components }) => {
return html`
<a href="${hit.abs_url}" class="md-search-result__link" tabindex="-1">
<div class="md-search-result__article md-typeset">
<div class="md-search-result__icon md-icon"></div>
<h1>${components.Highlight({ attribute: 'title', hit })}</h1>
<article>${components.Snippet({ attribute: 'content', hit })} </article>
</div>
</a>`
},
},
})
]);

search.start();
69 changes: 0 additions & 69 deletions docs/javascripts/search-worker.js

This file was deleted.

45 changes: 0 additions & 45 deletions docs/overrides/main.html
Original file line number Diff line number Diff line change
@@ -1,50 +1,5 @@
{% extends "base.html" %}

{% block config %}
{%- set app = {
"base": base_url,
"features": features,
"translations": {},
"search": base_url + "/javascripts/search-worker.js" | url
} -%}

<!-- Versioning -->
{%- if config.extra.version -%}
{%- set mike = config.plugins.get("mike") -%}
{%- if not mike or mike.config.version_selector -%}
{%- set _ = app.update({ "version": config.extra.version }) -%}
{%- endif -%}
{%- endif -%}

<!-- Tags -->
{%- if config.extra.tags -%}
{%- set _ = app.update({ "tags": config.extra.tags }) -%}
{%- endif -%}

<!-- Translations -->
{%- set translations = app.translations -%}
{%- for key in [
"clipboard.copy",
"clipboard.copied",
"search.result.placeholder",
"search.result.none",
"search.result.one",
"search.result.other",
"search.result.more.one",
"search.result.more.other",
"search.result.term.missing",
"select.version"
] -%}
{%- set _ = translations.update({ key: lang.t(key) }) -%}
{%- endfor -%}

<!-- Configuration -->
<script id="__config" type="application/json">
{{- app | tojson -}}
</script>
<!-- Add scripts that need to run afterwards here -->
{% endblock %}

{% block content %}
{{ super() }}
<script src="/flarelytics/client.js"></script>
Expand Down
32 changes: 32 additions & 0 deletions docs/overrides/partials/search.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<div class="md-search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" id="searchbox" class="md-search__input" name="query" aria-label="Search" placeholder="Search" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" required="">
<label class="md-search__icon md-icon" for="__search">

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"></path></svg>

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"></path></svg>
</label>
<nav class="md-search__options" aria-label="Search">

<button id="searchbox-clear" type="reset" class="md-search__icon md-icon" title="Clear" aria-label="Clear" tabindex="-1">

<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"></path></svg>
</button>
</nav>

<div class="md-search__suggest"></div>

</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" tabindex="0">
<div class="md-search-result">
<div class="md-search-result__meta" id="type-to-start-searching">Type to start searching</div>
<ol class="md-search-result__list" id="hits" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
Loading

0 comments on commit 8bd85d4

Please sign in to comment.