Skip to content

Commit

Permalink
Bring search bar into view on desktop (#1872)
Browse files Browse the repository at this point in the history
This commit changes how the search bar is brought into view on desktop as
brought up in #1860: when using one of the keyboard shortcuts to focus
the input, the entire page jumps to the top making you lose your scroll
position.  On mobile, technically smaller screens, this is remedied by
causing the input to slide into view on scroll up, but I don't believe
this is a desirable solution for desktop.

The following changes are introduced:

  * Using one of the keyboard shortcuts will focus the search input
    causing it to stick to the top.
  * It will continue to stick to the top so long as it is focused
    allowing you to scroll with it open.
  * The slide-on-scroll effect has been changed to only fire on
    touch-enabled devices as opposed to just smaller screens.  This is
    allows us to make the hexdocs window very small and still use
    keyboard shortcuts--Useful on laptops.

Closes #1860
  • Loading branch information
sodapopcan committed Mar 12, 2024
1 parent dcb1938 commit ac40c44
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 34 deletions.
24 changes: 23 additions & 1 deletion assets/css/layout.css
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,28 @@ body.sidebar-closed .content {
left: 0;
}

@media screen and (max-width: 768px) {
@media screen and (hover: hover) and (max-width: 768px) {
body.sidebar-opening .content {
left: 0;
width: 100%;
}

body.sidebar-closed .sidebar-button {
position: absolute;
top: 14px;
}

body.sidebar-closed .sidebar-button.fixed {
position: fixed;
padding: 16px 12px 18px 19px;
}

body.sidebar-closed .sidebar-button.fixed-top {
position: fixed;
}
}

@media screen and (hover: none) {
.content,
body.sidebar-opening .content {
left: 0;
Expand All @@ -137,6 +158,7 @@ body.sidebar-closed .content {

body.sidebar-closed .sidebar-button {
position: absolute;
top: 14px;
}

.sm-fixed {
Expand Down
24 changes: 17 additions & 7 deletions assets/css/search-bar.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
.top-search {
position: relative;
top: 0;
z-index: 101;
margin-top: 10px;
background-color: var(--background);
padding: 0.8rem 0;
}

@media (max-width: 480px) or ((min-width: 481px) and (max-width: 768px)) {
.top-search {
padding: 0.8rem 1.8rem 0.8rem 3rem;
margin-left: -1rem;
margin-right: -1rem;
}
}

.top-search.sticky {
position: sticky;
}

.search-settings {
Expand Down Expand Up @@ -114,13 +130,7 @@
color: var(--iconAction);
}

@media (max-width: 480px) or ((min-width: 481px) and (max-width: 768px)) {
.search-bar {
margin-left: 0px;
}
}

@media (max-width: 768px) {
@media (hover: none) {
.top-search {
margin-top: 0;
position: absolute;
Expand Down
13 changes: 12 additions & 1 deletion assets/js/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,21 @@ export function getProjectNameAndVersion () {
}

/**
* Return `true` if the client's OS is MacOS
* Return `true` if the client's OS is MacOS.
*
* @return {Boolean}
*/
export function isMacOS () {
return /(Mac|iPhone|iPod|iPad)/i.test(navigator.platform)
}

/**
* Return `true` if the client's device is touch-enabled.
*
* @return {Boolean}
*/
export function isTouchDevice () {
return (('ontouchstart' in window) ||
(navigator.maxTouchPoints > 0) ||
(navigator.msMaxTouchPoints > 0))
}
68 changes: 44 additions & 24 deletions assets/js/search-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ import {
AUTOCOMPLETE_CONTAINER_SELECTOR,
AUTOCOMPLETE_SUGGESTION_SELECTOR
} from './autocomplete/autocomplete-list'
import { isMacOS, qs } from './helpers'
import { isMacOS, isTouchDevice, qs } from './helpers'

const SEARCH_INPUT_SELECTOR = 'form.search-bar input'
const SEARCH_CLOSE_BUTTON_SELECTOR = 'form.search-bar .search-close-button'
const TOP_SEARCH_SELECTOR = '.top-search'

/**
* Initializes the sidebar search box.
Expand All @@ -34,6 +35,16 @@ export function setSearchInputValue (value) {
*/
export function focusSearchInput () {
const searchInput = qs(SEARCH_INPUT_SELECTOR)

if (!isTouchDevice()) {
qs(TOP_SEARCH_SELECTOR).classList.add('sticky')
if (window.scrollY === 0) {
qs('.sidebar-button').classList.add('fixed-top')
} else {
qs('.sidebar-button').classList.add('fixed')
}
}

searchInput.focus()
}

Expand Down Expand Up @@ -151,38 +162,47 @@ function hideAutocomplete () {
}

let lastScrollTop = window.scrollY
const topSearch = document.querySelector('.top-search')
const topSearch = document.querySelector(TOP_SEARCH_SELECTOR)
const sidebarMenu = document.getElementById('sidebar-menu')
const backgroundLayer = document.querySelector('.background-layer')
const scrollThreshold = 70 // Set a threshold for scroll, adjust as needed
const searchInput = qs(SEARCH_INPUT_SELECTOR)
const sidebarButton = qs('.sidebar-button')

window.addEventListener('scroll', function () {
const currentScroll = window.scrollY

// Add 'fixed' class when not at the top
if (currentScroll > scrollThreshold * 2) {
topSearch.classList.add('sm-fixed')
sidebarMenu.classList.add('sm-fixed')
backgroundLayer.classList.add('sm-fixed')
}
if (isTouchDevice()) {
// Add 'fixed' class when not at the top
if (currentScroll > scrollThreshold * 2) {
topSearch.classList.add('sm-fixed')
sidebarMenu.classList.add('sm-fixed')
backgroundLayer.classList.add('sm-fixed')
}

if (currentScroll === 0) {
// Remove 'fixed' class when at the top
topSearch.classList.remove('sm-fixed')
sidebarMenu.classList.remove('sm-fixed')
backgroundLayer.classList.remove('sm-fixed')
}
if (currentScroll === 0) {
// Remove 'fixed' class when at the top
topSearch.classList.remove('sm-fixed')
sidebarMenu.classList.remove('sm-fixed')
backgroundLayer.classList.remove('sm-fixed')
}

if (currentScroll > lastScrollTop && currentScroll > scrollThreshold) {
// Scrolling down and past the threshold
topSearch.classList.add('sm-hidden')
sidebarMenu.classList.add('sm-hidden')
backgroundLayer.classList.add('sm-hidden')
} else {
// Scrolling up or at the top of the page
topSearch.classList.remove('sm-hidden')
sidebarMenu.classList.remove('sm-hidden')
backgroundLayer.classList.remove('sm-hidden')
if (currentScroll > lastScrollTop && currentScroll > scrollThreshold) {
// Scrolling down and past the threshold
topSearch.classList.add('sm-hidden')
sidebarMenu.classList.add('sm-hidden')
backgroundLayer.classList.add('sm-hidden')
} else {
// Scrolling up or at the top of the page
topSearch.classList.remove('sm-hidden')
sidebarMenu.classList.remove('sm-hidden')
backgroundLayer.classList.remove('sm-hidden')
}
} else if (currentScroll !== lastScrollTop) {
topSearch.classList.remove('sticky')
sidebarButton.classList.remove('fixed')
sidebarButton.classList.remove('fixed-top')
searchInput.blur()
}

lastScrollTop = currentScroll <= 0 ? 0 : currentScroll
Expand Down
1 change: 0 additions & 1 deletion lib/ex_doc/formatter/html/templates/sidebar_template.eex
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,4 @@
<span class="sr-only">Settings</span>
</button>
</div>

</div>

0 comments on commit ac40c44

Please sign in to comment.