Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document Algolia DocSearch integration #394

Open
hammer opened this issue Sep 14, 2021 · 12 comments
Open

Document Algolia DocSearch integration #394

hammer opened this issue Sep 14, 2021 · 12 comments
Labels
enhancement New feature or request

Comments

@hammer
Copy link

hammer commented Sep 14, 2021

Description / Summary

I would like to use Algolia's DocSearch to get fast typeahead on our search box. There are instructions for how to integrate DocSearch with the RTD theme at readthedocs/sphinx_rtd_theme#761. I have tried to modify the CSS/JS for this theme but I can't make it work.

Value / benefit

This would allow users of this theme to have fast typeahead on their search box.

Implementation details

I have tried using inputSelector: '#search-input' in the JS and #search-input { overflow: visible; } in the CSS, but this does not work.

Tasks to complete

No response

@hammer hammer added the enhancement New feature or request label Sep 14, 2021
@welcome
Copy link

welcome bot commented Sep 14, 2021

Thanks for opening your first issue here! Engagement like this is essential for open source projects! 🤗

If you haven't done so already, check out EBP's Code of Conduct. Also, please try to follow the issue template as it helps other community members to contribute more effectively.

If your issue is a feature request, others may react to it, to raise its prominence (see Feature Voting).

Welcome to the EBP community! 🎉

@hammer
Copy link
Author

hammer commented Sep 14, 2021

I noticed while investigating this issue that the #search-input element has an autocomplete attribute that's currently set to off. I don't see any documentation on this attribute; do I perhaps need to set it to on? I tried doing that manually with Chrome developer tools and it didn't seem to help, but just thought I'd ask.

@hammer
Copy link
Author

hammer commented Sep 14, 2021

Okay strangely after a reload this is actually working now! The styling is not great as the search result text is cut off at the sidebar. If anyone with frontend skills sees this issue, I'd love your assistance making this look good...

@choldgraf
Copy link
Member

@hammer - did you ever get this one working? I agree it would be excellent to document this pattern. If there is some CSS tweaks we can make to improve the algolia search UI, then I'd be +1 on adding those in this theme.

@hammer
Copy link
Author

hammer commented Oct 19, 2021

@choldgraf we did in fact get this working! https://github.com/pystatgen/sgkit/pull/668 is the PR and you can try it live at https://pystatgen.github.io/sgkit/latest/.

From a styling perspective the only tricky part is to make the results box overflow the left sidebar. It would probably be better to have the search box on a topbar, similar to what you have on your personal site, but that level of customization is beyond my skill level.

We still need to figure out how to restrict the typeahead to a specific version, and it would be nice to tweak how some content is ranked and displayed, but overall I think the typeahead is a better search experience than having a separate search results page. Although I also haven't figured out how to get to a search results page with this plugin, you seem to have to open one of the typehead results...

@choldgraf
Copy link
Member

choldgraf commented Oct 19, 2021

whooooah it is beautiful! If you have a chance to write some short docs about the steps you followed, I am happy to review a PR!

@dylanh724
Copy link

dylanh724 commented Aug 16, 2024

@hammer Hey bud, your pull request is 404'd and this is from 2021 -- how did you get this working? Did you ever get it styled? Did you need autocomplete on to work? Does anyone have any advice here?

@dylanh724
Copy link

Hi @gregcaporaso , @rowanc1 , apologies I'm not quite sure who to ping for this -- do you guys know anything about this? I noticed this issue was opened in 2021, so I'm not quite sure if I should bump this (since it's still open) or create a new issue.

@gregcaporaso
Copy link
Member

@dylanh724, I'm sorry, I don't know anything about this one. Weirdly it looks like there are no pull requests (at all) associated with that repo now.

I suspect we should close this one with a note to reopen if it becomes relevant again.

@dylanh724
Copy link

dylanh724 commented Jan 16, 2025

I got it working. I ended up using a custom button to not have to worry about moving/rethemeing the Algolia one since book's is pretty cool and nicely positioned. I'd love to see official integration so we can remove some of our bloat :) Here's to get someone started:


Algolia Sphinx Setup Guide

Follow this normally. Then, override some stuff:

Conf.py

# conf.py

html_css_files = []
html_css_files.append("styles/css/algoliaDocSearchSphinxBookThemeSupport.css")

html_js_files = []
html_js_files.append(("js/algoliaDocSearchSphinxBookThemeSupport.js", {"defer": "defer"}))

# sphinx-book-theme doesn't contain the expected dev, so we inject it in via j2 template
docsearch_container = "#search-input" 

# ⚠️ Yours may look different, but minimally add "inject-algolia-docsearch.j2"
# I like to position it below the "search-button-field"
html_sidebars = {
    "**": [
        "navbar-logo",
        "search-button-field",
        "inject-algolia-docsearch.j2",  # <<<<
        "sbt-sidebar-nav",
    ],
}

SCSS

This is SCSS, but you can probably run it through an online parser if you wanted the raw CSS:

Core [S]CSS

// algoliaDocSearchSphinxBookThemeSupport.scss

/* 
##################################################################################
- You should parse this SCSS to CSS before building
- Initial template suggestion from yafimvo @ 
  https://github.com/jupyter-book/jupyter-book/issues/1324#issuecomment-1512757574 
##################################################################################
*/

/* -- sphinx-book-theme Support --------------------------------------------------------------------- */
/* Hide the old theme's (!Algolia's) search wrapper window when hitting Ctrl+K */
.search-button__wrapper, #search-input {
    display: none !important;
}

/* Make sure Algolia's search container is always on top */
.DocSearch.DocSearch-Container {
    z-index: 10000;
}

dialog#pst-search-dialog {
    /* Hide the sphinx-book-theme dialog that pops up on CTRL+K */
    display: none;

    &[hidden] {
        /* Handle sphinx-book-theme's dialog that still pops up on CTRL+K: Hide + prevent interaction */
        pointer-events: none;
        visibility: hidden;
    }
}

OPTIONAL [S]CSS: Custom Button (Use Theme's)

Append this if you want to hide Algolia's search bar to use the theme's:

// algoliaDocSearchSphinxBookThemeSupport.scss

/* -- Custom search bar (use Theme's search bar): Hide Algolia's ------------------------------------ */
/* This custom search bar pairs heavily with `../_static/js/algoliaDocSearchSphinxBookThemeSupport.js` that redirects clicks */

.sidebar-primary-item:has(#docsearch) {
    display:none
}

OPTIONAL [S]CSS: Narrow Screen Search Bar Workarounds

This is actually an independent theme bug where the search bar poofs when the screen is narrow enough - it shouldn't hide the search bar, but since it's related, let's resolve it here before we open a new ticket.

TODO: Convert this section into an independent issue

// algoliaDocSearchSphinxBookThemeSupport.scss

/* -- General .search-button-field fixes for sphinx-book-theme workarounds -------- */
.sidebar-primary-item {
    /* Fix theme search button field for narrow screens */
    .search-button-field {
        display: flex; /* Align children horizontally */
        justify-content: space-between; /* Space between icon, text, and shortcut */
        align-items: center; /* Vertically */
        width: 100%; /* Ensure it spans the full width; TODO: necessary? */

        /* Undo the display:none and text oddities for narrow screens */
        .search-button__default-text {
            display: unset;
            flex-grow: 1; /* Allow text to take up the remaining space */
            text-align: left;
            font-size: 14px;
        }

        /* CTRL+K text is hidden on narrow screens */
        .search-button__kbd-shortcut {
            display: unset;
        }
    }
}

_templates/inject-algolia-docsearch.j2

Remember in conf.py, we included this? All we're doing is injecting an empty #docsearch div:

<!-- Algolia DocSearch requires a #docsearch id wrapper [anywhere] to inject the search bar -->
<!-- This would normally create a search bar, but we'll hide it with CSS, styling our theme's bar -->
<!-- (!) Note `../_sass/algoliaDocSearchSphinxBookThemeSupport.scss` -->
<!-- (!) Note `../_static/js/customAlgoliaDocSearchBtn.js` -->
<div id="docsearch"></div>

OPTIONAL: Use the theme's button instead of Algolia's

Prereqs (All Stated Above)

  1. You added the conf.py js
  2. You added the optional css rule to hide Algolia's search bar
  3. You added the entire .js file

JS

Note the regions of required <> optional:

// ###############################################################################
// _static/js/algoliaDocSearchSphinxBookThemeSupport.js
// - Removes the old search `dialog` element from DOM (REQUIRED)
// - Closes the sidebar dialog, if open (mobile), to prevent overlap
// - Use a custom search btn (sphinx-book-theme's native search btn):
//   - Emulates the CTRL+K keypress to trigger the search overlay
//   - Focuses the search input after a short delay
//   - Adds a global listener for CTRL+K keypress
// ###############################################################################

// Constants
const OLD_SEARCH_DIALOG_SELECTOR_NAME = 'pst-search-dialog';  // REQUIRED
const SIDEBAR_DIALOG_SELECTOR = 'dialog#pst-primary-sidebar-modal';
const THEME_SEARCH_BUTTON_SELECTOR = '.search-button__button';
const NEW_SEARCH_INPUT_SELECTOR = 'input#DocSearch-Input';

// =================================================================================================
// [REQUIRED] SPHINX-BOOK-THEME-SUPPORT :: Remove old dialog from DOM
// =================================================================================================

// On DOMContentLoaded, remove the dialog element if it exists; and remove the old CTLR+K listener to prevent errs
document.addEventListener('DOMContentLoaded', () => {
	const dialog = document.getElementById(OLD_SEARCH_DIALOG_SELECTOR_NAME);
	if (dialog) {
		dialog.remove();
		console.info(`Dialog with id "${OLD_SEARCH_DIALOG_SELECTOR_NAME}" has been removed.`);
	}

       const sphinxPyDataCtrlKListener = getEventListeners(window).keydown[0].listener;
       window.removeEventListener("keydown", sphinxPyDataCtrlKListener, true);
});

// =================================================================================================
// [OPTIONAL] SPHINX-BOOK-THEME-SUPPORT :: 
// Use theme's btn, close left sidebar on mobile, focus input, emulate CTRL+K, add global listener
// =================================================================================================

// Initialize the script
const initializeSearchButton = () => {
	const searchButtons = document.querySelectorAll(THEME_SEARCH_BUTTON_SELECTOR);

	searchButtons.forEach(button => {
		button.addEventListener('click', handleSearchButtonClick);
	});

	// Add global listener for CTRL+K
	document.addEventListener('keydown', handleCtrlKKeypress);

	console.log('[js/customAlgoliaDocSearchBtn.js] Search buttons and global CTRL+K listener initialized');
};

// Handle the search button click
const handleSearchButtonClick = () => {
	console.log('[js/customAlgoliaDocSearchBtn.js] Search button clicked');

	closeSidebarDialog();
	emulateCtrlKTriggerSearchOverlay();
	focusSearchInput();
};

// Handle CTRL+K keypress
const handleCtrlKKeypress = (event) => {
	if (event.key === 'k' && event.ctrlKey) {
		console.log('[js/customAlgoliaDocSearchBtn.js] CTRL+K pressed');
		closeSidebarDialog(); // Close the sidebar if open
		// Let the default Algolia logic for CTRL+K handle the rest
	}
};

// Close the sidebar dialog if open
const closeSidebarDialog = () => {
	const sidebarDialog = document.querySelector(SIDEBAR_DIALOG_SELECTOR);
	if (sidebarDialog?.open) {
		console.log('[js/customAlgoliaDocSearchBtn.js] Closing sidebar dialog');
		sidebarDialog.close();
	}
};

// Emulate CTRL+K to trigger the search overlay
const emulateCtrlKTriggerSearchOverlay = () => {
	console.log('[js/customAlgoliaDocSearchBtn.js] emulateCtrlKTriggerSearchOverlay');
	const event = new KeyboardEvent('keydown', {
		key: 'k',
		ctrlKey: true,
		bubbles: true
	});
	focusSearchInput();
	document.dispatchEvent(event);
};

// Focus the search input after a short delay
const focusSearchInput = () => {
	setTimeout(() => {
		const searchInput = document.querySelector(NEW_SEARCH_INPUT_SELECTOR);
		if (searchInput) {
			console.log('[js/customAlgoliaDocSearchBtn.js] focusSearchInput');
			searchInput.focus();
		} else {
			console.log(`[js/customAlgoliaDocSearchBtn.js] Search input ${NEW_SEARCH_INPUT_SELECTOR} not found`);
		}
	}, 100); // Adjust the delay if necessary
};

// Run the initialization
initializeSearchButton();

Source Available

There's a source-available example from the production site here: https://docs.goxbe.io/ -- See dev branch for recent/prettier updates.

Hope this helps someone that can glue this all together minimally. You guys may also want to work with Algolia directly on this one; I have an open issue requesting official theme support to hopefully make it easier than above: algolia/sphinx-docsearch#62 ( CC @kai687 )

@dylanh724
Copy link

dylanh724 commented Jan 16, 2025

^ Update:

  • In the end, I actually had to add a JS file to remove the dialog#pst-primary-sidebar-modal from DOM since dialog (new to me 😜 ) can't seem to be completely removed through CSS: I wasn't able to click-through the first time (and every other time) I opened the dialog via CTRL+K
    • Removing it from DOM resolved this with a js file.
  • I also realized that my JS file also works-around a mobile-sidebar-wont-close-on-click bug , so I supposed my js isn't just for a custom button. I'll edit + split it up with obvious comment regions when I'm on a break.

EDIT: Updated code ✅

TL;DR: Quite the pain to manually add support, but possible and proved working in a production env (see dev branch if checking out src) :) If this can all be abstracted to prevent bloat/confusion and repro'd on a minimal project, that'd rock.

@dylanh724
Copy link

dylanh724 commented Jan 24, 2025

Update: To prevent sphinx-book-theme errs, I also need to unregister the old CTRL+K hotkey, but it's anonymous. Raised a ticket with sphinx-pydata-theme (sphinx-book-theme's parent).

Edit: I read you have pydata theme support - you probably get console errors on that theme, too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

4 participants