Skip to content

Commit

Permalink
ENH: Search button shows up on mobile (#832)
Browse files Browse the repository at this point in the history
* ENH: Search button shows up on mobile

* Remove crufty comments
  • Loading branch information
choldgraf committed Jul 24, 2022
1 parent a7d74f5 commit 2e1269f
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 82 deletions.
99 changes: 55 additions & 44 deletions src/pydata_sphinx_theme/assets/scripts/index.js
Expand Up @@ -168,19 +168,8 @@ function scrollToActive() {
/*******************************************************************************
* Search
*/
var changeShortcutText = () => {
// Change the search hint to `meta key` if we are a Mac
let forms = document.querySelectorAll("form.bd-search");
var isMac = window.navigator.platform.toUpperCase().indexOf("MAC") >= 0;
if (isMac) {
forms.forEach(
(f) => (f.querySelector("kbd.kbd-shortcut__modifier").innerText = "⌘")
);
}
};

/** Find any search forms on the page and return their input element */
var findSearchInput = () => {
// find the search form(s) on the page
let forms = document.querySelectorAll("form.bd-search");
if (!forms.length) {
// no search form found
Expand All @@ -200,18 +189,21 @@ var findSearchInput = () => {
}
};

/**
* Activate the search field on the page.
* - If there is a search field already visible it will be activated.
* - If not, then a search field will pop up.
*/
var toggleSearchField = () => {
// focus/unfocus the search field (and if it's an auto-hiding one,
// show/hide it too)
// Find the search input to highlight
let input = findSearchInput();
let button = document.getElementById("bd-search-button");

// if the input field is the hidden one (the one associated with the
// search button) then toggle the button state (to show/hide the field)
let hidden_input = document.querySelector(
".search-button__search-container input"
);
if (input === hidden_input) {
button.classList.toggle("show");
let searchPopupWrapper = document.querySelector(".search-button__wrapper");
let hiddenInput = searchPopupWrapper.querySelector("input");
if (input === hiddenInput) {
searchPopupWrapper.classList.toggle("show");
}
// when toggling off the search field, remove its focus
if (document.activeElement === input) {
Expand All @@ -223,31 +215,49 @@ var toggleSearchField = () => {
}
};

// Add an event listener for toggleSearchField() for Ctrl/Cmd + K
window.addEventListener(
"keydown",
(event) => {
let input = findSearchInput();
// toggle on Ctrl+k or ⌘+k
if ((event.ctrlKey || event.metaKey) && event.code == "KeyK") {
event.preventDefault();
toggleSearchField();
}
// also allow Escape key to hide (but not show) the dynamic search field
else if (document.activeElement === input && event.code == "Escape") {
toggleSearchField();
}
},
true
);

window.onload = function () {
changeShortcutText();
let button = document.getElementById("bd-search-button");
let overlay = document.querySelector("div.search-button__overlay");
if (button) {
button.onclick = toggleSearchField;
/** Add an event listener for toggleSearchField() for Ctrl/Cmd + K */
var addEventListenerForSearchKeyboard = () => {
window.addEventListener(
"keydown",
(event) => {
let input = findSearchInput();
// toggle on Ctrl+k or ⌘+k
if ((event.ctrlKey || event.metaKey) && event.code == "KeyK") {
event.preventDefault();
toggleSearchField();
}
// also allow Escape key to hide (but not show) the dynamic search field
else if (document.activeElement === input && event.code == "Escape") {
toggleSearchField();
}
},
true
);
};

/** Change the search hint to `meta key` if we are a Mac */
var changeSearchShortcutKey = () => {
let forms = document.querySelectorAll("form.bd-search");
var isMac = window.navigator.platform.toUpperCase().indexOf("MAC") >= 0;
if (isMac) {
forms.forEach(
(f) => (f.querySelector("kbd.kbd-shortcut__modifier").innerText = "⌘")
);
}
};

/** Activate callbacks for search button popup */
var setupSearchButtons = () => {
changeSearchShortcutKey();
addEventListenerForSearchKeyboard();

// Add the search button trigger event callback
document.querySelectorAll(".search-button__button").forEach((btn) => {
btn.onclick = toggleSearchField;
});

// Add the search button overlay event callback
let overlay = document.querySelector(".search-button__overlay");
if (overlay) {
overlay.onclick = toggleSearchField;
}
Expand All @@ -262,3 +272,4 @@ window.onload = function () {
$(addModeListener);
$(scrollToActive);
$(addTOCInteractivity);
$(setupSearchButtons);
67 changes: 42 additions & 25 deletions src/pydata_sphinx_theme/assets/styles/components/_search.scss
Expand Up @@ -69,18 +69,36 @@
}

// __search-container will only show up when we use the search pop-up bar
.search-button__search-container {
.search-button__search-container,
.search-button__overlay {
display: none;
// Center in middle of screen just underneath header
position: fixed;
z-index: $zindex-fixed;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
right: 1rem;
margin-top: 0.5rem;
width: 90%;
max-width: 800px;
}
.search-button__wrapper.show {
.search-button__search-container {
display: flex;
// Center in middle of screen just underneath header
position: fixed;
z-index: $zindex-modal;
top: 30%;
left: 50%;
transform: translate(-50%, -50%);
right: 1rem;
margin-top: 0.5rem;
width: 90%;
max-width: 800px;
}

.search-button__overlay {
display: flex;
position: fixed;
z-index: $zindex-modal-backdrop;
background-color: black;
opacity: 0.5;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
}

form.bd-search {
flex-grow: 1;
Expand All @@ -95,23 +113,22 @@
}
}

.search-button__overlay {
display: none;
}
/**
* Button behavior on mobile / wide so it shows up in the header on mobile.
*/

#bd-search-button.show {
~ .search-button__search-container {
// The navbar end version should only show on wide screens
.navbar-end__search-button-container {
display: none;
@include media-breakpoint-up($breakpoint-header) {
display: flex;
}
}

~ .search-button__overlay {
display: flex;
position: fixed;
background-color: black;
opacity: 0.5;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
// The one next to the hamburger menu only shows on narrow screens
.search-button-container--mobile {
margin-left: auto;
@include media-breakpoint-up($breakpoint-header) {
display: none;
}
}
@@ -1,14 +1,4 @@
{# Search page has its own UI / UX for search #}
<!-- A button that will trigger a search field to be displayed on click. -->
{% set containerClass="search-button__search-container" %}

<!-- An overlay that will expand in the background and cause the search to disappear when clicked -->
<button class="btn btn-sm navbar-btn search-button" id="bd-search-button" title="{{ _('Search') }}">
{# A button that, when clicked, will trigger a search popup overlay #}
<button class="btn btn-sm navbar-btn search-button search-button__button" title="{{ _('Search') }}">
<i class="fas fa-search"></i>
</button>

{#- This will be hidden by default until click -#}
<div class="search-button__overlay"></div>
<div class="{{ containerClass }}">
{% include "../components/search-field.html" %}
</div>
9 changes: 9 additions & 0 deletions src/pydata_sphinx_theme/theme/pydata_sphinx_theme/layout.html
Expand Up @@ -51,6 +51,15 @@
<input type="checkbox" class="sidebar-toggle" name="__secondary" id="__secondary">
<label class="overlay overlay-secondary" for="__secondary"></label>

<!-- A search field pop-up that will only show when the search button is clicked -->

<div class="search-button__wrapper">
<div class="search-button__overlay"></div>
<div class="search-button__search-container">
{% include "../components/search-field.html" %}
</div>
</div>

{% include "sections/announcement.html" %}

{% block docs_navbar %}
Expand Down
Expand Up @@ -6,6 +6,11 @@
{% endfor %}
</div>

{# A search button to show up only on mobile #}
<div class="search-button-container--mobile">
{%- include "../components/search-button.html" %}
</div>

<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbar-collapsible" aria-controls="navbar-collapsible" aria-expanded="false" aria-label="{{ _('Toggle navigation') }}">
<span class="fas fa-bars"></span>
</button>
Expand All @@ -21,6 +26,9 @@
</div>

<div id="navbar-end">
<div class="navbar-end-item navbar-end__search-button-container">
{% include "../components/search-button.html" %}
</div>
{% for navbar_item in theme_navbar_end %}
<div class="navbar-end-item">
{% include navbar_item %}
Expand Down
Expand Up @@ -30,7 +30,7 @@ show_toc_level = 1
navbar_align = content
navbar_start = navbar-logo.html
navbar_center = navbar-nav.html
navbar_end = search-button.html, theme-switcher.html, navbar-icon-links.html
navbar_end = theme-switcher.html, navbar-icon-links.html
header_links_before_dropdown = 5
left_sidebar_end = sidebar-ethical-ads.html
footer_items = copyright.html, sphinx-version.html
Expand Down

0 comments on commit 2e1269f

Please sign in to comment.